diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-04-20 16:25:39 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-04-20 16:45:45 +0000 |
| commit | 22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53 (patch) | |
| tree | f54ada7db6958c6b92064b13fff8294336111b64 | |
| parent | add wxLua alv-wx (diff) | |
| download | alive-22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53.tar.gz alive-22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53.zip | |
export and export* to create alive modules
See #16
| -rw-r--r-- | alv/base/builtin.moon | 2 | ||||
| -rw-r--r-- | alv/builtin.moon | 83 | ||||
| -rw-r--r-- | alv/cell.moon | 5 | ||||
| -rw-r--r-- | alv/copilot.moon | 17 | ||||
| -rw-r--r-- | alv/cycle.moon | 13 | ||||
| -rw-r--r-- | alv/init.moon | 20 | ||||
| -rw-r--r-- | alv/load.moon | 43 | ||||
| -rwxr-xr-x | docs/gen/index | 4 |
8 files changed, 142 insertions, 45 deletions
diff --git a/alv/base/builtin.moon b/alv/base/builtin.moon index fd36c69..b9e7e55 100644 --- a/alv/base/builtin.moon +++ b/alv/base/builtin.moon @@ -88,7 +88,7 @@ class Builtin builtin\eval scope, cell\tail! - __tostring: => "<#{@@__name} #{@head}>" + __tostring: => "<#{@@__name}[#{@tag}] #{@head}>" __inherited: (cls) => cls.__base.__tostring = @__tostring { diff --git a/alv/builtin.moon b/alv/builtin.moon index ab3a9a0..9b88bd4 100644 --- a/alv/builtin.moon +++ b/alv/builtin.moon @@ -7,11 +7,14 @@ -- @module builtin import Builtin, Op, FnDef, Input, val, evt from require 'alv.base' import ValueStream, LiteralValue from require 'alv.stream.value' +import Error from require 'alv.error' import Result from require 'alv.result' import Cell from require 'alv.cell' import Scope from require 'alv.scope' import Tag from require 'alv.tag' import op_invoke from require 'alv.invoke' +import load from require 'alv.cycle' +lfs = require 'lfs' doc = ValueStream.meta meta: @@ -82,6 +85,16 @@ All arguments have to be evaltime constant." Result! +load_module = (name, tag) -> + Error.wrap "loading module '#{name}'", -> + ok, lua = pcall require, "alv-lib.#{name}" + if ok + ValueStream.wrap lua + else + result,_ = load.loadfile "#{name}.alv" + assert result, "empty return value" + result.value + require_ = ValueStream.meta meta: name: 'require' @@ -95,11 +108,10 @@ require_ = ValueStream.meta assert #tail == 1, "'require' takes exactly one parameter" result = L\push tail[1]\eval, scope - name = result\const! + name = result\const!\unwrap 'str' L\trace @, "loading module #{name}" - scope = ValueStream.wrap require "alv-lib.#{name\unwrap 'str'}" - Result :value + Result value: load_module name, @tag import_ = ValueStream.meta meta: @@ -115,10 +127,9 @@ current scope." L\trace "evaling #{@}" assert #tail > 0, "'import' requires at least one arguments" - for child in *tail - name = (child\quote scope)\unwrap 'sym' - value = ValueStream.wrap require "alv-lib.#{name}" - scope\set name, Result :value + for i, child in ipairs tail + name = child\quote(scope)\unwrap 'sym' + scope\set name, Result value: load_module name, @tag\clone Tag i Result! import_star = ValueStream.meta @@ -134,14 +145,53 @@ Requires modules `sym1`, `sym2`, … and merges them into the current scope." L\trace "evaling #{@}" assert #tail > 0, "'import' requires at least one arguments" - - for child in *tail - name = (child\quote scope)\unwrap 'sym' - value = ValueStream.wrap require "alv-lib.#{name}" + for i, child in ipairs tail + value = load_module child\quote(scope)\unwrap('sym'), @tag\clone Tag i scope\use value\unwrap 'scope' Result! +export_ = ValueStream.meta + meta: + name: 'export' + summary: "Evaluate definitions in a new scope and return it." + examples: { '(export expr1 [expr2…])' } + description: " +Evaluate `expr1`, `expr2`, … in a new Scope and return scope." + + value: class extends Builtin + eval: (scope, tail) => + scope = Scope scope + children = [expr\eval scope for expr in *tail] + Result :children, value: ValueStream.wrap scope + +export_star = ValueStream.meta + meta: + name: 'export*' + summary: "Export specific symbol definitions as a module/scope." + examples: { '(export* sym1 [sym2…])', '(export*)' } + description: " +Creates a scope containing the symbols `sym1`, `sym2`, … and returns it. + +Copies the containing scope if no symbols are given." + + value: class extends Builtin + eval: (scope, tail) => + L\trace "evaling #{@}" + new_scope = Scope! + + children = if #tail == 0 + for k,result in pairs scope.values + new_scope\set k, result + result + else + for child in *tail + name = child\quote(scope)\unwrap 'sym' + with result = scope\get name + new_scope\set name, result + + Result :children, value: ValueStream.wrap new_scope + fn = ValueStream.meta meta: name: 'fn' @@ -185,7 +235,7 @@ function is invoked." assert #tail == 3, "'defn' takes exactly three arguments" { name, params, body } = tail - name = (name\quote scope)\unwrap 'sym' + name = name\quote(scope)\unwrap 'sym' assert params.__class == Cell, "'defn's second argument has to be an expression" param_symbols = for param in *params.children assert param.type == 'sym', "function parameter declaration has to be a symbol" @@ -204,7 +254,7 @@ function is invoked." do_expr = ValueStream.meta meta: - name: 'do_expr' + name: 'do' summary: "Evaluate multiple expressions in a new scope." examples: { '(do expr1 [expr2…])' } description: " @@ -213,7 +263,8 @@ Evaluate `expr1`, `expr2`, … and return the value of the last expression." value: class extends Builtin eval: (scope, tail) => scope = Scope scope - Result children: [expr\eval scope for expr in *tail] + children = [expr\eval scope for expr in *tail] + Result :children, value: children[#children].value if_ = ValueStream.meta meta: @@ -300,7 +351,7 @@ print = ValueStream.meta else L\print @inputs.value! -{ +Scope.from_table { :doc :trace, 'trace!': trace_, :print @@ -308,6 +359,8 @@ print = ValueStream.meta require: require_ import: import_ 'import*': import_star + export: export_ + 'export*': export_star true: ValueStream.meta meta: diff --git a/alv/cell.moon b/alv/cell.moon index f7e9773..d341dde 100644 --- a/alv/cell.moon +++ b/alv/cell.moon @@ -173,6 +173,11 @@ class RootCell extends Cell head: => ValueStream.sym 'do' tail: => @children + clone: (parent) => + tag = @tag\clone parent + children = [child\clone parent for child in *@children] + RootCell tag, children, @white + stringify: => buf = '' buf ..= @white[0] diff --git a/alv/copilot.moon b/alv/copilot.moon index 3d1523e..e5868bb 100644 --- a/alv/copilot.moon +++ b/alv/copilot.moon @@ -6,13 +6,7 @@ lfs = require 'lfs' import Scope from require 'alv.scope' import Registry from require 'alv.registry' import Error from require 'alv.error' -import program from require 'alv.parsing' -globals = Scope.from_table require 'alv.builtin' - -slurp = (file) -> - file = io.open file, 'r' - with file\read '*all' - file\close! +import loadfile from require 'alv.load' spit = (file, str) -> file = io.open file, 'w' @@ -59,14 +53,7 @@ class Copilot eval: => @registry\begin_eval! - ok, ast = Error.try "parsing '#{@file}'", program\match, slurp @file - if not (ok and ast) - L\print ast or Error 'syntax', "failed to parse" - @registry\rollback_eval! - return - - scope = Scope globals - ok, root = Error.try "evaluating '#{@file}'", ast\eval, scope, @registry + ok, root, ast = Error.try "running '#{@file}'", loadfile, @file if not ok L\print root @registry\rollback_eval! diff --git a/alv/cycle.moon b/alv/cycle.moon index f5b7e15..dba100f 100644 --- a/alv/cycle.moon +++ b/alv/cycle.moon @@ -11,16 +11,21 @@ -- import somewhere from require 'alv.cycle' -- somewhere.Something ... -- --- Make sure cycle:load() is called before you access or dereference +-- Make sure cycle:resolve() is called before you access or dereference -- `somewhere`. -load = => - for name, module in pairs @ +unresolved = {} + +resolve = => + for name, module in pairs unresolved for k, v in pairs require "alv.#{name}" module[k] = v + unresolved = {} + setmetatable {}, __index: (key) => - return load if key == 'load' + return resolve if key == 'resolve' with v = {} + rawset unresolved, key, v rawset @, key, v diff --git a/alv/init.moon b/alv/init.moon index 8b7a01b..f2fed2f 100644 --- a/alv/init.moon +++ b/alv/init.moon @@ -9,6 +9,8 @@ if _VERSION == 'Lua 5.1' error msg a, msg, ... +cycle = require 'alv.cycle' + version = require 'alv.version' import Logger from require 'alv.logger' import ValueStream, EventStream, IOStream from require 'alv.stream' @@ -21,11 +23,13 @@ import Tag from require 'alv.tag' import Cell, RootCell from require 'alv.cell' import program from require 'alv.parsing' -with require 'alv.cycle' - \load! +cycle\resolve! + +globals = require 'alv.builtin' + +cycle\resolve! import Copilot from require 'alv.copilot' -globals = Scope.from_table require 'alv.builtin' --- exports -- @table exports @@ -61,10 +65,10 @@ globals = Scope.from_table require 'alv.builtin' assert (program\match str), Error 'syntax', "failed to parse" eval: (str, inject) -> - scope = Scope nil, globals - scope\use inject if inject + scope = Scope globals + scope\use inject if inject - ast = assert (program\match str), "failed to parse" - result = ast\eval scope - result\const! + ast = assert (program\match str), "failed to parse" + result = ast\eval scope + result\const! } diff --git a/alv/load.moon b/alv/load.moon new file mode 100644 index 0000000..f3f7927 --- /dev/null +++ b/alv/load.moon @@ -0,0 +1,43 @@ +---- +-- Functions for loading strings and files of alive code. +-- +-- @module load +import Result from require 'alv.result' +import Builtin from require 'alv.base' +import Scope from require 'alv.scope' +import Error from require 'alv.error' +import program from require 'alv.parsing' +builtin = require 'alv.builtin' + +slurp = (file) -> + file = io.open file, 'r' + with file\read '*all' + file\close! + +--- Attempt to load alive code from string. +-- +-- @tparam string code the code to load +-- @tparam ?string file name of the source file (for error reporting) +-- @treturn Result +-- @treturn AST the parsed and updated AST +loadstring = (code, file='(unnamed)') -> + Error.wrap "evaluating '#{file}'", -> + ast = program\match code + if not ast + error Error 'syntax', "failed to parse" + + scope = Scope builtin + result = ast\eval scope + result, ast + +--- Attempt to load alive code from a file. +-- +-- @tparam string file filepath of the source file +-- @treturn Result +-- @treturn AST the parsed and updated AST +loadfile = (file) -> loadstring (slurp file), file + +{ + :loadstring + :loadfile +} diff --git a/docs/gen/index b/docs/gen/index index 5b06b9d..96f85f0 100755 --- a/docs/gen/index +++ b/docs/gen/index @@ -42,7 +42,7 @@ spit OUT, layout h2 a "builtins", href: '#builtins' p "These definitions are automatically loaded into the global Scope of every alive session." - ul for key, val in opairs require 'alv.builtin' - li render key, ValueStream.wrap val + ul for key, val in opairs (require 'alv.builtin').values + li render key, val.value } } |
