mirror of
https://github.com/janet-lang/janet
synced 2025-07-15 16:32:53 +00:00
More work on bootstrapping code. Have working macro expansion.
This commit is contained in:
parent
f0545865a8
commit
a39a6fd97f
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,6 +2,9 @@
|
|||||||
/client/gst
|
/client/gst
|
||||||
gst
|
gst
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
*.genh
|
||||||
|
|
||||||
# Tags
|
# Tags
|
||||||
tags
|
tags
|
||||||
|
|
||||||
|
17
core/stl.c
17
core/stl.c
@ -1020,6 +1020,21 @@ static int gst_stl_compile(Gst *vm) {
|
|||||||
gst_c_return(vm, gst_compile(vm, env, gst_arg(vm, 0)));
|
gst_c_return(vm, gst_compile(vm, env, gst_arg(vm, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get vm->env */
|
||||||
|
static int gst_stl_getenv(Gst *vm) {
|
||||||
|
gst_c_return(vm, gst_wrap_table(vm->env));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set vm->env */
|
||||||
|
static int gst_stl_setenv(Gst *vm) {
|
||||||
|
GstValue newEnv = gst_arg(vm, 0);
|
||||||
|
if (newEnv.type != GST_TABLE) {
|
||||||
|
gst_c_throwc(vm, "expected table");
|
||||||
|
}
|
||||||
|
vm->env = newEnv.data.table;
|
||||||
|
return GST_RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
/* Bootstraping */
|
/* Bootstraping */
|
||||||
/****/
|
/****/
|
||||||
@ -1058,6 +1073,8 @@ static const GstModuleItem std_module[] = {
|
|||||||
{"parse-status", gst_stl_parser_status},
|
{"parse-status", gst_stl_parser_status},
|
||||||
{"parse", gst_stl_parse},
|
{"parse", gst_stl_parse},
|
||||||
/* Compile */
|
/* Compile */
|
||||||
|
{"getenv", gst_stl_getenv},
|
||||||
|
{"setenv", gst_stl_setenv},
|
||||||
{"compile", gst_stl_compile},
|
{"compile", gst_stl_compile},
|
||||||
/* Other */
|
/* Other */
|
||||||
{"not", gst_stl_not},
|
{"not", gst_stl_not},
|
||||||
|
78
libs/bootstrap.gst
Normal file
78
libs/bootstrap.gst
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
# This file is executed without any macro expansion (macros are not
|
||||||
|
# yet defined). Cannot use macros or anything outside the stl.
|
||||||
|
|
||||||
|
# Helper for macro expansion
|
||||||
|
(def macroexpander (fn [x env f]
|
||||||
|
(if (= (type x) :tuple)
|
||||||
|
(if (> (length x) 0)
|
||||||
|
(do
|
||||||
|
(def first (get x 0))
|
||||||
|
(def macros (get env :macros))
|
||||||
|
(if macros
|
||||||
|
(do
|
||||||
|
(def macro (get macros first))
|
||||||
|
(if macro
|
||||||
|
(f (apply macro (slice x 1)))
|
||||||
|
x))
|
||||||
|
x)
|
||||||
|
x)
|
||||||
|
x)
|
||||||
|
x)))
|
||||||
|
|
||||||
|
# Macro expansion
|
||||||
|
(def macroexpand (fn [x env]
|
||||||
|
(macroexpander x (if env env (getenv)) macroexpander)))
|
||||||
|
|
||||||
|
# Function to create macros
|
||||||
|
(def global-macro (fn [name f]
|
||||||
|
(def env (getenv))
|
||||||
|
(def env-macros (get env :macros))
|
||||||
|
(def macros (if env-macros env-macros {}))
|
||||||
|
(set! env :macros macros)
|
||||||
|
(set! macros (symbol name) f)
|
||||||
|
f))
|
||||||
|
|
||||||
|
# Make defn
|
||||||
|
(global-macro "defn" (fn [name &]
|
||||||
|
(tuple 'def name (apply tuple 'fn &))))
|
||||||
|
|
||||||
|
# Make defmacro
|
||||||
|
(global-macro "defmacro" (fn [name &]
|
||||||
|
(tuple global-macro (string name) (apply tuple 'fn &))))
|
||||||
|
|
||||||
|
# Comment returns nil
|
||||||
|
(global-macro "comment" (fn [] nil))
|
||||||
|
|
||||||
|
# The source file to read from
|
||||||
|
(var *sourcefile* stdin)
|
||||||
|
|
||||||
|
# The *read* macro gets the next form from the source file, and
|
||||||
|
# returns it. It is a var and therefor can be overwritten.
|
||||||
|
(var *read* (fn []
|
||||||
|
(def b (buffer))
|
||||||
|
(def p (parser))
|
||||||
|
(while (not (parse-hasvalue p))
|
||||||
|
(read *sourcefile* 1 b)
|
||||||
|
(if (= (length b) 0)
|
||||||
|
(error "parse error: unexpected end of source"))
|
||||||
|
(parse-charseq p b)
|
||||||
|
(if (= (parse-status p) :error)
|
||||||
|
(error (string "parse error: " (parse-consume p))))
|
||||||
|
(clear b))
|
||||||
|
(parse-consume p)))
|
||||||
|
|
||||||
|
# Evaluates a form by macro-expanding it, compiling it, and
|
||||||
|
# then executing it.
|
||||||
|
(def eval (fn [x]
|
||||||
|
(def func (compile (macroexpand x)))
|
||||||
|
(if (= :function (type func))
|
||||||
|
(func)
|
||||||
|
(error (string "compiler error: " func)))))
|
||||||
|
|
||||||
|
# A simple repl for testing.
|
||||||
|
(while true
|
||||||
|
(def t (thread (fn []
|
||||||
|
(while true
|
||||||
|
(print (eval (*read*)))))))
|
||||||
|
(print (tran t)))
|
@ -1,26 +0,0 @@
|
|||||||
(var *sourcefile* stdin)
|
|
||||||
|
|
||||||
(var *compile* (fn [x]
|
|
||||||
(def ret (compile x))
|
|
||||||
(if (= :function (type ret))
|
|
||||||
ret
|
|
||||||
(error (string "compile error: " ret)))))
|
|
||||||
|
|
||||||
(var *read* (fn []
|
|
||||||
(def b (buffer))
|
|
||||||
(def p (parser))
|
|
||||||
(while (not (parse-hasvalue p))
|
|
||||||
(read *sourcefile* 1 b)
|
|
||||||
(if (= (length b) 0)
|
|
||||||
(error "unexpected end of source"))
|
|
||||||
(parse-charseq p b)
|
|
||||||
(clear b))
|
|
||||||
(parse-consume p)))
|
|
||||||
|
|
||||||
(def eval (fn [x &]
|
|
||||||
(apply (*compile* x) &)))
|
|
||||||
|
|
||||||
(def t (thread (fn []
|
|
||||||
(while true
|
|
||||||
(eval (*read*))))))
|
|
||||||
(print (tran t))
|
|
Loading…
x
Reference in New Issue
Block a user