@@ -12,6 +12,7 @@ ScriptML is a research project and toy compiler, written in TypeScript, that exp
1212- ** Recursion and totality checks**
1313- ** Dependent function types (Π-types)**
1414- ** IO via embedded thunks** that lower to JS functions
15+ - ** Modules and imports** with qualified names and ` open `
1516
1617The compiler emits either standalone JavaScript or directly evaluates programs.
1718
@@ -46,7 +47,7 @@ npm test
4647
4748# # Language overview
4849
49- ScriptML has a ** typed λ-calculus core** with Nats, Lists, user ADTs, and IO .
50+ ScriptML has a ** typed λ-calculus core** with Nats, Lists, user ADTs, IO, and now ** modules ** .
5051
5152# ## Basic expressions
5253
116117length [zero, succ zero, succ (succ zero)]
117118` ` `
118119
120+ ---
121+
122+ # ## Modules
123+
124+ ScriptML supports a lightweight module system.
125+
126+ * A file can begin with ` module < Name> ` (optional; defaults to the filename).
127+ * Import another file with ` import " path/to/file.sml" as Alias` .
128+ * Use qualified names like ` Math.add` .
129+ * Use ` open < Module> ` to bring a module’s values into scope without qualification.
130+
131+ Example module:
132+
133+ ` ` ` ocaml
134+ module Math
135+
136+ val add = fun (a: _) -> fun (b: _) -> a + b;
137+ val sub = fun (a: _) -> fun (b: _) -> a - b;
138+ ` ` `
139+
140+ Use it:
141+
142+ ` ` ` ocaml
143+ import " std/math.sml" as Math
144+
145+ println (" 3 + 4 = " ^ Math.add 3 4)
146+ ` ` `
147+
148+ Or with ` open` :
149+
150+ ` ` ` ocaml
151+ import " std/math.sml" as Math
152+ open Math
153+
154+ println (" 3 - 4 = " ^ sub 3 4)
155+ ` ` `
156+
157+ All ` val` and ` type` decls in a module are exported by default.
158+ ` open` is just syntactic sugar for creating local aliases.
159+
160+ ---
161+
119162# ## IO
120163
121164IO is modeled with thunks (` () => value` ) and ` bind` / ` pure` :
@@ -144,9 +187,14 @@ Builtins provided via `__io`:
144187A simplified EBNF for ScriptML:
145188
146189` ` `
147- program ::= { decl } term
190+ program ::= [ " module" Ident ] { import | decl } [ term ]
191+
192+ import ::= " import" Str " as" Ident
193+ | " open" Ident
148194
149195decl ::= " type" Ident { Ident } " =" ctor { " |" ctor }
196+ | " val" Ident " =" term " ;"
197+
150198ctor ::= Ident [ " of" type { " ," type } ]
151199
152200term ::= let | fun | if | match | expr
@@ -163,6 +211,7 @@ pattern ::= "zero"
163211
164212expr ::= expr atom | atom
165213atom ::= Ident
214+ | Ident " ." Ident // qualified variable
166215 | Int
167216 | Str
168217 | " zero"
@@ -172,6 +221,7 @@ atom ::= Ident
172221
173222type ::= type " ->" type
174223 | " Nat"
224+ | " Unit"
175225 | Ident
176226 | Ident type
177227 | " (" type " )"
@@ -244,11 +294,11 @@ play 21
244294 * ` lexer.ts`
245295 * ` parser.ts` (Pratt parser)
246296 * ` elab_emit.ts` (elaboration + JS codegen)
247- * ` compiler.ts` (top-level driver)
297+ * ` compiler.ts` (top-level driver, import/module loader )
248298* Tests in ` __tests__` , goldens in ` tests/fixtures`
249299
250300---
251301
252302# # License
253303
254- MIT
304+ MIT
0 commit comments