aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-04-20 16:25:39 +0000
committers-ol <s-ol@users.noreply.github.com>2020-04-20 16:45:45 +0000
commit22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53 (patch)
treef54ada7db6958c6b92064b13fff8294336111b64
parentadd wxLua alv-wx (diff)
downloadalive-22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53.tar.gz
alive-22fa7e3786ff4d5035c6827ed59c3bcf2e49ae53.zip
export and export* to create alive modules
See #16
-rw-r--r--alv/base/builtin.moon2
-rw-r--r--alv/builtin.moon83
-rw-r--r--alv/cell.moon5
-rw-r--r--alv/copilot.moon17
-rw-r--r--alv/cycle.moon13
-rw-r--r--alv/init.moon20
-rw-r--r--alv/load.moon43
-rwxr-xr-xdocs/gen/index4
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
}
}