af3fc57

Faddle · faddle.git · Tickets

Branches > main > af3fc57 > files

commit EVERYTHING I can never remeber to commit shit

Grahp, 2026-07-18

Commit: af3fc57c2ca99cbb43155891d3b956146cebb35f
Parent: 5e1b1bd

7 changed files:

org/faddle.fdl modified (view file)

@@ -1,4 +1,8 @@ (module :org.faddle)  (def __rt (require :org.faddle.lang.rt))-(def plus (fn [x y] (__rt:plus x y)))+; TODO remove rt from packages?+; Or just have some notion of private modules in their own table+(def plus __rt:plus)+; . is a placeholder for nothing, so it can be the result of calling a function that doesn't return anything+(def . ((fn [])))

org/faddle/lang/compile.lua modified (view file)

@@ -1,42 +1,92 @@ 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+local munge = symbol.munge+local module = symbol.module++local lisp_print = require("org.faddle.lang.print").print  -- Still bad :p local FN = intern("fn")+local LET = intern("let")+local DO = intern("do")  local compile -local function compile_fn(form)+local gensym_number = 0+local function gensym()+  gensym_number = gensym_number + 1+  return "G__" .. gensym_number+end++local function ret(statement)+  return statement and "return " or ""+end++local function compile_fn(form, statement)   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"+  return ret(statement) .. "function() " .. compile(first(body), true) .. " end"+end++-- If I'm just using the same lexical stuff as Lua, how do builtin Lua modules work?+-- In Lua you can just say `io`, but I'd like to wrap these libraries in something like `lua.io`+-- to make it clear where they're coming from...+-- Not sure how I could do that+-- I also want to check locals and fail during compilation if you reference a non-existent local+-- Well `io` is just something you'd have to import in Faddle, since the compiler can just look at what+-- modules have been imported, and `io` won't be one of them.+-- So then `lua.io` or whatever can be defined by Faddle, and map to `io`.+local function compile_let(form, statement)+  local args = rest(form)+  local bindings = first(args)+  local body = rest(args)+  assert(type(bindings) == "table" and #bindings % 2 == 0, "Let requires an even number of binding forms")+  assert(#bindings == 2)+  assert(count(body) == 1)+  local sym = bindings[1]+  local binding = bindings[2]+  if statement then+    return "local " .. munge(sym) .. "=" .. compile(binding) .. ";" .. compile(first(body), true)+  else+    return "return (function()" .. compile_let(form, not statement) .. " end)()"+  end end  --- Returns a string of Lua source code from the form-compile = function(form)+-- TODO needs to compile returns vs not returns, I think...+-- So this may need to encode the context of whether this is in an expression or statement context+compile = function(form, statement)   if is_list(form) then-    if count(form) == 0 then return "__rt.list()" end-    if first(form) == FN then return compile_fn(form) end+    -- if count(form) == 0 then return "__rt.list()" end+    if count(form) == 0 then return ret(statement) .. "require('org.faddle').list()" end+    -- If it's a literal number or string you can compile directly to a lookup+    -- Symbols still need to be checked whether they resolve to a string or number though+    if first(form) == FN then return compile_fn(form, statement) end+    if first(form) == LET then return compile_let(form, statement) end+    print(lisp_print(form))+    assert(count(form) == 1, "uhhh")+    return ret(statement) .. compile(first(form)) .. "()"     -- macro expansion :D-    -- rt functions?+    -- core functions+    -- vars that are local, however you're supposed to know that :p+  elseif is_symbol(form) then+    assert(not module(form), "can't compile symbols with modules yet :(")+    return ret(statement) .. munge(form)   else     local t = type(form)     if t == "number" or t == "nil" or t == "boolean" then-      return tostring(form)+      return ret(statement) .. tostring(form)     elseif t == "string" then-      return string.format("%q", form)

Show all 115 lines

org/faddle/lang/eval.lua modified (view file)

@@ -59,6 +59,7 @@ local MODULE = intern("module") local QUOTE = intern("quote") local FN = intern("fn")+local LET = intern("let")  -- Should eventually be in core/boot ofc they're just here now so I can test functions before figuring out modules local temp_vars =@@ -81,16 +82,22 @@   -- Should fail if you're looking up a non-existent local, but not otherwise   -- There's currently no way to tell the difference between an undefined local and a nil local   return temp_vars[sym] or modules[env.current_module][munge(sym)]++  -- This is always looking up a global+  -- So this is either a symbol with a module or a simple symbol that's been referred...+  -- If the sym refers to a macro, error saying you can't do that 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)   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)+    local eval_k = eval(k, env)+    if eval_k == nil then+      error("Table key must be a value, but nothing was provided")+    else+      ret[eval_k] = eval(v, env)+    end   end   return ret end@@ -132,7 +139,8 @@     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+    if f == FN     then return execute(compile(form, true), "eval_fn") end+    if f == LET     then return execute(compile(form, true), "eval_let") end      form = map_eval(form, env)     return call(first(form), rest(form))

org/faddle/lang/read.lua modified (view file)

@@ -26,7 +26,7 @@  local function read(s)   local pos = 1-  -- If #s returns the number of bytes this would be wrong+  -- TODO If #s returns the number of bytes this would be wrong?   local len = #s    local read_value

org/faddle/lang/rt.lua modified (view file)

@@ -2,5 +2,7 @@ local LIST = require("org.faddle.lang.list")  local list = LIST.list+local type = type -return {list = list}+return {list = list,+        type = type}

org/faddle/lang/symbol.lua modified (view file)

@@ -30,7 +30,7 @@  local function name(sym)   if is_symbol(sym) then-    return sym[NAME]+    return assert(sym[NAME])   else     error("Cannot get the symbol name of type " .. type(sym), 2)   end@@ -40,7 +40,7 @@   if is_symbol(sym) then     return sym[MODULE]   else-    error("Cannot get the symbol table of type " .. type(sym), 2)+    error("Cannot get the symbol module of type " .. type(sym), 2)   end end 

test.lua modified (view file)

@@ -8,7 +8,7 @@ local apply = LIST.apply local lisp_print = require("org.faddle.lang.print").print --- Returns whether 2 objects are structurally equal at the point of calling, even if they are mutable+--- Returns whether 2 objects are structurally equal at the point of calling, even if they are mutable (i.e. tables) local function eq(x,y)   if x == y then return true end   if is_list(x) and is_list(y) then@@ -143,4 +143,18 @@ teq(read_eval("(plus)"), 0) teq(read_eval("(plus 1 2 3)"), 6) +-- local compiler = require("org.faddle.lang.compile")+-- local execute = compiler.execute+-- local compile = compiler.compile++teq(read_eval("(let [x 42] 42)"), 42)+teq(read_eval("((fn [] 42))"), 42)+teq(read_eval("(let [f (fn [] 42)] (f))"), 42)++-- Later+-- teq(read_eval("(let [x 1 y 2] [x y])"), {1, 2})+-- teq(read_eval("((fn [x] x) :abc)"), :abc)++---+ print("Yay it worked")