8432b65
Branches > main > 8432b65 > files
Add compiler
Commit: 8432b653b28cd9ec957cf18e6ffbe24188b9492d
Parent: d2ef4c4
3 changed files:
org/faddle/lang/compile.lua view file
@@ -0,0 +1,57 @@+local LIST = require("org.faddle.lang.list")+local is_list = LIST.is_list+local cons = LIST.cons+local count = LIST.count+local first = LIST.first+local rest = LIST.rest+local apply = LIST.apply+local empty = LIST.empty+local symbol = require("org.faddle.lang.symbol")+local is_symbol = symbol.is_symbol+local intern = symbol.intern++-- Still bad :p+local FN = intern("fn")++local compile++local function compile_fn(form)+ local args = rest(form)+ local fn_args = first(args)+ local body = rest(args)+ assert(#fn_args == 0)+ assert(count(body) == 1)+ return "function() return " .. compile(first(body)) .. " end"+end++--- Returns a string of Lua source code from the form+compile = function(form)+ if is_list(form) then+ if count(form) == 0 then return "__rt.list()" end+ if first(form) == FN then return compile_fn(form) end+ -- macro expansion :D+ -- rt functions?+ else+ local t = type(form)+ if t == "number" or t == "nil" or t == "boolean" then+ return tostring(form)+ elseif t == "string" then+ return string.format("%q", form)+ else+ error("Cannot compile form of type '" .. t .. "'")+ end+ end+end++local loadfn = loadstring or load++local function execute(lua_source, chunk_name)+ local chunk, err = loadfn("local __rt = require('org.faddle.lang.rt');return " .. lua_source, chunk_name)+ if not chunk then+ error(err)+ else+ return chunk()+ end+end++return {compile = compile, execute = execute}org/faddle/lang/eval.lua view file
@@ -10,6 +10,10 @@ local is_symbol = symbol.is_symbol local intern = symbol.intern +local compiler = require("org.faddle.lang.compile")+local compile = compiler.compile+local execute = compiler.execute+ local eval -- Table of module names -> module tables?@@ -21,16 +25,21 @@ -- And re-defining updates the var and calls its handler or whatever, or calls an update_var() idk, and it also updates the module table local function def(var_name, args, env) assert(is_symbol(var_name), "def must be called with a symbol")+ assert(modules[env.current_module] ~= nil, "Cannot define var in non-existent module '" .. env.current_module .. "'") local val = eval(first(args), env) -- Doesn't add to the return table right now -- Probably want to munge names so they're easier to use from Lua. -- I'm not sure whether like 'foo?' and 'is_foo' should be the same symbol or just munged to produce the same thing.- env[env.current_module][var_name] = val+ print(env.current_module)+ print(var_name)+ print(env.user)+ modules[env.current_module][var_name] = val return var_name end local function module(mod_name, env) if type(mod_name) ~= "string" then error("First argument to module must be a string!") end+ -- Why not? if package.loaded[mod_name] and not modules[mod_name] then error("Cannot override already defined Lua module " .. mod_name) else@@ -50,6 +59,7 @@ local DEF = intern("def") local MODULE = intern("module") local QUOTE = intern("quote")+local FN = intern("fn") -- Should eventually be in core/boot ofc they're just here now so I can test functions before figuring out modules local temp_functions =@@ -73,8 +83,15 @@ end -- Not quite sure how to do this...+-- Do tables need to be compiled into Lua?+-- Not simple ones, but others may benefit, I'm not sure. local function eval_table(t, env)- return t+ local ret = {}+ for k, v in pairs(t) do+ -- Could end up with holes, but that's the user's fault+ ret[eval(k, env)] = eval(v, env)+ end+ return ret end local function map_eval(lst, env)@@ -114,6 +131,7 @@ if f == QUOTE then return second(form) end if f == MODULE then return module(second(form), env) end if f == DEF then return def(second(form), rest(rest(form)), env) end+ if f == FN then return execute(compile(form), "eval_fn") end form = map_eval(form, env) return call(first(form), rest(form))org/faddle/lang/rt.lua view file
@@ -0,0 +1,6 @@++local LIST = require("org.faddle.lang.list")++local list = LIST.list++return {list = list}