pre-srfi / static-scheme

11 stars 0 forks source link

Boundary protocol and DSL #7

Open lassik opened 3 years ago

lassik commented 3 years ago

Using a library granularity for the time being, there should probably be three top-level forms:

The static+dynamic DSL would allow defining at least the following things:

lassik commented 3 years ago

For exporting static procedures to dynamic Scheme, I'd recommend just going with a normal (export ...) in a define-static-library. The type inference can figure out the type signature, so the export clause doesn't need to repeat the signature.

If we allow importing dynamic Scheme procedures into static libraries, as we probably should, the annotation must be hand-written somewhere. TypeScript has some system where they have auxiliary files (similar to Corba Interface Definition Language but simpler?) for dynamic JavaScript libraries to say what their types are.

aijony commented 3 years ago

I don't think you need a separate define-library, not to say it is a bad idea, but what I imagined was:

(define-library (example static+dynamic)
    (export a b)   
    (import (rename (steme)
        (define define:)))
    (begin
        (define a 2)                  ; dynamic variable
        (define: b (the integer 2)))) ; statically typed

(define-library (example static)
    (export c)   
    (import (steme))
    (begin
        (define c 2)))                ; static variable

So instead of a library being static or dynamic, the imported keywords and defined variables would be. Is there any disadvantage to this compared to declaring the library as static?

mnieper commented 3 years ago

Yes, it may be enough to distinguish between exports with a well-defined type and all other exports, which cannot be imported into Steme without giving them explicit type annotations at the import level.

One reason why @lassik used the new keyword define-static-library might be so that ordinary Scheme is not confused by seeing a define-library form that, however, includes extensions that are only understood by Steme.

PS In your example, why wouldn't a be a statically typed variable? The type can obviously be easily inferred.

PPS Long before we finalize the library system, we should get the type system at the expression level done.

lassik commented 3 years ago

Continuing from https://github.com/pre-srfi/static-scheme/issues/11#issuecomment-723340472

(define-static-library-from-dynamic (scheme set)
  (import (static base)
          (static set)
          (static comparator))
  (export (set-intersection (-> (set a) (set a) (set a)))
          (set-xor          (-> (set a) (set a) (set a)))
          (set-map          (-> (comparator b) (-> a b) (set a)))))

(define-static-library (example)
  (import (static base)
          (static vector)
          (scheme set))
  ...)
lassik commented 3 years ago

The more different scenarios I think through, the better it seems to have all the static code confined into static libraries, and to have all the FFI definitions in separate interface libraries. The static code is supposed to be purer than the dynamic code, and the FFI will be messy by comparison no matter how it's done. The same guarantees about type inference and type checking don't hold. It just seems clearest to separate the fundamentally different stuff. No matter how convenient c-lambda is in Gambit...