From 4a5262c95c911d0f77c20b5d855ad8fcc8a5b88a Mon Sep 17 00:00:00 2001 From: Reid 'arrdem' McKenzie Date: Sat, 21 Aug 2021 20:02:54 -0600 Subject: [PATCH] Making headway towards a runnable state --- projects/lilith/BUILD | 16 +------ projects/lilith/src/lilith/designdoc.lil | 2 +- projects/lilith/src/python/lilith/__main__.py | 32 ++++++++++---- .../lilith/src/python/lilith/grammar.lark | 16 ++++--- .../lilith/src/python/lilith/interpreter.py | 4 +- tools/python/defs.bzl | 42 ++++++++++++++++++- 6 files changed, 80 insertions(+), 32 deletions(-) diff --git a/projects/lilith/BUILD b/projects/lilith/BUILD index 05c23d1..f58e9a0 100644 --- a/projects/lilith/BUILD +++ b/projects/lilith/BUILD @@ -1,5 +1,6 @@ py_project( - name = "lib", + name = "lilith", + main = "src/python/lilith/__main__.py", lib_deps = [ py_requirement("lark"), py_requirement("pyyaml"), @@ -9,16 +10,3 @@ py_project( py_requirement("hypothesis"), ], ) - -zapp_binary( - name = "lilith", - main = "src/python/lilith/__main__.py", - deps = [ - ":lib", - # FIXME: Due to zapp bug(s), replicating requirements here. - py_requirement("lark"), - py_requirement("pyyaml"), - py_requirement("markdown"), - py_requirement("prompt_toolkit"), - ], -) diff --git a/projects/lilith/src/lilith/designdoc.lil b/projects/lilith/src/lilith/designdoc.lil index 5b61545..804e5f9 100644 --- a/projects/lilith/src/lilith/designdoc.lil +++ b/projects/lilith/src/lilith/designdoc.lil @@ -36,7 +36,7 @@ FIXME: We need the object language !def[openapi, yaml[]] -!def[main, lilith[]] +!def[main, lang[lilith]] ; is importing a bang-operation? print[str.join["", [pitch, syntax]]] diff --git a/projects/lilith/src/python/lilith/__main__.py b/projects/lilith/src/python/lilith/__main__.py index 2151a12..a6c01fe 100644 --- a/projects/lilith/src/python/lilith/__main__.py +++ b/projects/lilith/src/python/lilith/__main__.py @@ -75,21 +75,23 @@ def batch(opts, args, runtime): main = Symbol(main) # Register - runtime.modules[mod.name] = mod + runtime.modules.update({mod.name: mod}) print("DEBUG: batch mode") print( yaml.dump( { "type": "runtime", - "name": runtime.name, + "name": runtime.name.name, "modules": { - m.name: { + m.name.name: { "defs": {dname.name: repr(d) for dname, d in m.defs.items()} } for m in runtime.modules.values() }, - } + }, + default_flow_style=False, + sort_keys=False, ) ) @@ -125,11 +127,27 @@ if __name__ == "__main__": sys.path.insert(0, _e) # Building up a bootstrap interface for going out to many Python features. - runtime = Runtime("__runtime__", Symbol(opts.prelude), {}) + runtime = Runtime(Symbol("__runtime__"), Symbol(opts.prelude), {}) + + def _lil(runtime=None, + module=None, + body=None, + name=None): + """The implementation of the Lilith lang as an eval type.""" + expr = parse_expr(body) + return eval(runtime, module, Bindings(), expr) + bootstrap = Module( - "lilith.bootstrap", + Symbol("lilith.bootstrap"), [], - {Symbol("py"): lambda *args, body=None, **kwargs: eval(body)}, + { + # The foundational meaning of lang[] + Symbol("lang"): lambda evaluator, body=None: evaluator(body), + # The Python FFI escape hatch + Symbol("py"): lambda *args, body=None, **kwargs: eval(body), + # The Lilith self-interpreter + Symbol("lilith"): _lil, + }, ) runtime.modules[Symbol(bootstrap.name)] = bootstrap prelude_mod = read_buffer( diff --git a/projects/lilith/src/python/lilith/grammar.lark b/projects/lilith/src/python/lilith/grammar.lark index c6245bc..2bb163e 100644 --- a/projects/lilith/src/python/lilith/grammar.lark +++ b/projects/lilith/src/python/lilith/grammar.lark @@ -10,10 +10,9 @@ STRING: /""".*?"""/ | /".*?"/ int: INT float: FLOAT number: int | float -word: "nil" -> nil - | "true" -> true - | "false" -> false - | WORD ("." WORD)* -> word + +word: WORD ("." WORD)* -> word + string: STRING list: "[" (expr ("," expr)*)? "]" @@ -21,7 +20,14 @@ list: "[" (expr ("," expr)*)? "]" pair: expr ":" expr dict: "{" (pair ("," pair)*)? "}" -atom: number | word | string | list | dict +atom: number + | word + | string + | list + | dict + | "nil" -> nil + | "true" -> true + | "false" -> false application: word "[" arguments? "]" diff --git a/projects/lilith/src/python/lilith/interpreter.py b/projects/lilith/src/python/lilith/interpreter.py index a379b0d..a69fb81 100644 --- a/projects/lilith/src/python/lilith/interpreter.py +++ b/projects/lilith/src/python/lilith/interpreter.py @@ -72,9 +72,7 @@ def eval(ctx: Runtime, mod: Module, locals: Bindings, expr): return lookup(ctx, mod, locals, expr) elif isinstance(expr, Apply): - # FIXME (arrdem 2021-08-21): - # Apply should be (apply ). - # Now no distinction is made between strings ("") and symbols/barewords + # Evaluate the call target fun = eval(ctx, mod, locals, expr.target) # Evaluate the parameters args = eval(ctx, mod, locals, expr.args.positionals) diff --git a/tools/python/defs.bzl b/tools/python/defs.bzl index edc4a91..180c115 100644 --- a/tools/python/defs.bzl +++ b/tools/python/defs.bzl @@ -8,6 +8,10 @@ load("@rules_python//python:defs.bzl", _py_library = "py_library", ) +load("@rules_zapp//zapp:zapp.bzl", + "zapp_binary", +) + def py_requirement(*args, **kwargs): """A re-export of requirement()""" @@ -146,6 +150,7 @@ py_resources = rule( ) def py_project(name=None, + main=None, lib_srcs=None, lib_deps=None, lib_data=None, @@ -184,8 +189,10 @@ def py_project(name=None, "**/*.pyc", ]) + lib_name = name if not main else "lib" + py_library( - name=name, + name=lib_name, srcs=lib_srcs, deps=lib_deps, data=lib_data, @@ -198,12 +205,43 @@ def py_project(name=None, ], ) + if main: + py_binary( + name=name, + main=main, + srcs=lib_srcs, + deps=lib_deps, + data=lib_data, + imports=[ + "src/python", + "src/resources", + ], + visibility = [ + "//visibility:public", + ], + ) + + zapp_binary( + name=name + ".zapp", + main=main, + srcs=lib_srcs, + deps=lib_deps, + data=lib_data, + imports=[ + "src/python", + "src/resources", + ], + visibility = [ + "//visibility:public", + ], + ) + for src in test_srcs: if "test_" in src: py_pytest( name=src.split("/")[-1], srcs=[src] + [f for f in test_srcs if "test_" not in f], - deps=[name] + (test_deps or []), + deps=[lib_name] + (test_deps or []), data=test_data, imports=[ "test/python",