Making headway towards a runnable state

This commit is contained in:
Reid 'arrdem' McKenzie 2021-08-21 20:02:54 -06:00
parent 8dd071625f
commit 4243a9355c
6 changed files with 80 additions and 32 deletions

View file

@ -1,5 +1,6 @@
py_project( py_project(
name = "lib", name = "lilith",
main = "src/python/lilith/__main__.py",
lib_deps = [ lib_deps = [
py_requirement("lark"), py_requirement("lark"),
py_requirement("pyyaml"), py_requirement("pyyaml"),
@ -9,16 +10,3 @@ py_project(
py_requirement("hypothesis"), 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"),
],
)

View file

@ -36,7 +36,7 @@ FIXME: We need the object language
!def[openapi, yaml[]] !def[openapi, yaml[]]
!def[main, lilith[]] !def[main, lang[lilith]]
; is importing a bang-operation? ; is importing a bang-operation?
print[str.join["", [pitch, syntax]]] print[str.join["", [pitch, syntax]]]

View file

@ -75,21 +75,23 @@ def batch(opts, args, runtime):
main = Symbol(main) main = Symbol(main)
# Register # Register
runtime.modules[mod.name] = mod runtime.modules.update({mod.name: mod})
print("DEBUG: batch mode") print("DEBUG: batch mode")
print( print(
yaml.dump( yaml.dump(
{ {
"type": "runtime", "type": "runtime",
"name": runtime.name, "name": runtime.name.name,
"modules": { "modules": {
m.name: { m.name.name: {
"defs": {dname.name: repr(d) for dname, d in m.defs.items()} "defs": {dname.name: repr(d) for dname, d in m.defs.items()}
} }
for m in runtime.modules.values() 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) sys.path.insert(0, _e)
# Building up a bootstrap interface for going out to many Python features. # 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( 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 runtime.modules[Symbol(bootstrap.name)] = bootstrap
prelude_mod = read_buffer( prelude_mod = read_buffer(

View file

@ -10,10 +10,9 @@ STRING: /""".*?"""/ | /".*?"/
int: INT int: INT
float: FLOAT float: FLOAT
number: int | float number: int | float
word: "nil" -> nil
| "true" -> true word: WORD ("." WORD)* -> word
| "false" -> false
| WORD ("." WORD)* -> word
string: STRING string: STRING
list: "[" (expr ("," expr)*)? "]" list: "[" (expr ("," expr)*)? "]"
@ -21,7 +20,14 @@ list: "[" (expr ("," expr)*)? "]"
pair: expr ":" expr pair: expr ":" expr
dict: "{" (pair ("," pair)*)? "}" dict: "{" (pair ("," pair)*)? "}"
atom: number | word | string | list | dict atom: number
| word
| string
| list
| dict
| "nil" -> nil
| "true" -> true
| "false" -> false
application: word "[" arguments? "]" application: word "[" arguments? "]"

View file

@ -72,9 +72,7 @@ def eval(ctx: Runtime, mod: Module, locals: Bindings, expr):
return lookup(ctx, mod, locals, expr) return lookup(ctx, mod, locals, expr)
elif isinstance(expr, Apply): elif isinstance(expr, Apply):
# FIXME (arrdem 2021-08-21): # Evaluate the call target
# Apply should be (apply <expr> <args> <kwargs>).
# Now no distinction is made between strings ("") and symbols/barewords
fun = eval(ctx, mod, locals, expr.target) fun = eval(ctx, mod, locals, expr.target)
# Evaluate the parameters # Evaluate the parameters
args = eval(ctx, mod, locals, expr.args.positionals) args = eval(ctx, mod, locals, expr.args.positionals)

View file

@ -8,6 +8,10 @@ load("@rules_python//python:defs.bzl",
_py_library = "py_library", _py_library = "py_library",
) )
load("@rules_zapp//zapp:zapp.bzl",
"zapp_binary",
)
def py_requirement(*args, **kwargs): def py_requirement(*args, **kwargs):
"""A re-export of requirement()""" """A re-export of requirement()"""
@ -146,6 +150,7 @@ py_resources = rule(
) )
def py_project(name=None, def py_project(name=None,
main=None,
lib_srcs=None, lib_srcs=None,
lib_deps=None, lib_deps=None,
lib_data=None, lib_data=None,
@ -184,8 +189,41 @@ def py_project(name=None,
"**/*.pyc", "**/*.pyc",
]) ])
lib_name = name if not main else "lib"
py_library( py_library(
name=lib_name,
srcs=lib_srcs,
deps=lib_deps,
data=lib_data,
imports=[
"src/python",
"src/resources",
],
visibility = [
"//visibility:public",
],
)
if main:
py_binary(
name=name, 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, srcs=lib_srcs,
deps=lib_deps, deps=lib_deps,
data=lib_data, data=lib_data,
@ -203,7 +241,7 @@ def py_project(name=None,
py_pytest( py_pytest(
name=src.split("/")[-1], name=src.split("/")[-1],
srcs=[src] + [f for f in test_srcs if "test_" not in f], 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, data=test_data,
imports=[ imports=[
"test/python", "test/python",