Skip to content

Commit

Permalink
export and export* to create alive modules
Browse files Browse the repository at this point in the history
See #16
  • Loading branch information
s-ol committed Apr 20, 2020
1 parent 8b9d1ac commit 22fa7e3
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 45 deletions.
2 changes: 1 addition & 1 deletion alv/base/builtin.moon
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Builtin

builtin\eval scope, cell\tail!

__tostring: => "<#{@@__name} #{@head}>"
__tostring: => "<#{@@__name}[#{@tag}] #{@head}>"
__inherited: (cls) => cls.__base.__tostring = @__tostring

{
Expand Down
83 changes: 68 additions & 15 deletions alv/builtin.moon
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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'
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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'
Expand Down Expand Up @@ -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"
Expand All @@ -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: "
Expand All @@ -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:
Expand Down Expand Up @@ -300,14 +351,16 @@ print = ValueStream.meta
else
L\print @inputs.value!

{
Scope.from_table {
:doc
:trace, 'trace!': trace_, :print

:def, :use
require: require_
import: import_
'import*': import_star
export: export_
'export*': export_star

true: ValueStream.meta
meta:
Expand Down
5 changes: 5 additions & 0 deletions alv/cell.moon
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
17 changes: 2 additions & 15 deletions alv/copilot.moon
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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!
Expand Down
13 changes: 9 additions & 4 deletions alv/cycle.moon
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 12 additions & 8 deletions alv/init.moon
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
Expand Down Expand Up @@ -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!
}
43 changes: 43 additions & 0 deletions alv/load.moon
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 2 additions & 2 deletions docs/gen/index
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

0 comments on commit 22fa7e3

Please sign in to comment.