Cleaned up code generation to have less cruft.
This commit is contained in:
parent
d3a5fc73bc
commit
6882862d0f
@ -29,13 +29,11 @@ macro block [for %key -> %value in %dict %body] =:
|
|||||||
assert ((%value's "type") == "Var") ".."
|
assert ((%value's "type") == "Var") ".."
|
||||||
|For loop has the wrong type for the value variable. Expected Var, but got: \%value's "type"\
|
|For loop has the wrong type for the value variable. Expected Var, but got: \%value's "type"\
|
||||||
".."
|
".."
|
||||||
|do
|
|
||||||
|local vars = setmetatable({}, {__index=vars})
|
|local vars = setmetatable({}, {__index=vars})
|
||||||
|for k, v in pairs(\%dict as lua\) do
|
|for k, v in pairs(\%dict as lua\) do
|
||||||
| \%key as lua\, \%value as lua\ = k, v
|
| \%key as lua\, \%value as lua\ = k, v
|
||||||
| \%body as lua\
|
| \%body as lua\
|
||||||
|end
|
|end
|
||||||
|end
|
|
||||||
|
|
||||||
# Membership testing
|
# Membership testing
|
||||||
rule [%item is in %list, %list contains %item, %list has %item] =:
|
rule [%item is in %list, %list contains %item, %list has %item] =:
|
||||||
@ -72,7 +70,7 @@ macro [%list ->* %indices] =:
|
|||||||
".."|(\%ret\)
|
".."|(\%ret\)
|
||||||
|
|
||||||
# Assignment
|
# Assignment
|
||||||
macro block [..]
|
macro statement [..]
|
||||||
%list's %index = %new_value, %index st in %list = %new_value, %index nd in %list = %new_value
|
%list's %index = %new_value, %index st in %list = %new_value, %index nd in %list = %new_value
|
||||||
%index rd in %list = %new_value, %index th in %list = %new_value, %index in %list = %new_value
|
%index rd in %list = %new_value, %index th in %list = %new_value, %index in %list = %new_value
|
||||||
%list -> %index = %new_value
|
%list -> %index = %new_value
|
||||||
|
@ -16,7 +16,7 @@ macro statement [if %condition %if_body else %else_body] =:
|
|||||||
|end
|
|end
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
macro block [return] =: "return nil"
|
macro statement [return] =: "do return end"
|
||||||
macro block [return %return-value] =: ".."
|
macro block [return %return-value] =: ".."
|
||||||
|return \%return-value as lua\
|
|return \%return-value as lua\
|
||||||
|
|
||||||
@ -117,9 +117,8 @@ macro block [when %body] =:
|
|||||||
%result join=: ".."
|
%result join=: ".."
|
||||||
|
|
|
|
||||||
|do
|
|do
|
||||||
| local ret
|
|
||||||
| \(lua expr "vars.thunk.value") as lua\
|
| \(lua expr "vars.thunk.value") as lua\
|
||||||
| return ret
|
| goto finished_when
|
||||||
|end
|
|end
|
||||||
..else:
|
..else:
|
||||||
if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"):
|
if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"):
|
||||||
@ -132,11 +131,10 @@ macro block [when %body] =:
|
|||||||
%result join=: ".."
|
%result join=: ".."
|
||||||
|
|
|
|
||||||
|if \%condition as lua\ then
|
|if \%condition as lua\ then
|
||||||
| local ret
|
|
||||||
| \(lua expr "vars.thunk.value") as lua\
|
| \(lua expr "vars.thunk.value") as lua\
|
||||||
| return ret
|
| goto finished_when
|
||||||
|end
|
|end
|
||||||
|
%result join=: "\n::finished_when::"
|
||||||
%result
|
%result
|
||||||
|
|
||||||
# Switch statement
|
# Switch statement
|
||||||
@ -160,9 +158,8 @@ macro block [when %branch-value %body] =:
|
|||||||
%result join=: ".."
|
%result join=: ".."
|
||||||
|
|
|
|
||||||
|do
|
|do
|
||||||
| local ret
|
|
||||||
| \(lua expr "vars.thunk.value") as lua\
|
| \(lua expr "vars.thunk.value") as lua\
|
||||||
| return ret
|
| goto finished_when
|
||||||
|end
|
|end
|
||||||
..else:
|
..else:
|
||||||
if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"):
|
if (lua expr "#vars.condition_bits == 1 and vars.condition_bits[1].type ~= 'Word'"):
|
||||||
@ -175,9 +172,9 @@ macro block [when %branch-value %body] =:
|
|||||||
%result join=: ".."
|
%result join=: ".."
|
||||||
|
|
|
|
||||||
|if compiler.utils.equivalent(branch_condition, \%condition as lua\) then
|
|if compiler.utils.equivalent(branch_condition, \%condition as lua\) then
|
||||||
| local ret
|
|
||||||
| \(lua expr "vars.thunk.value") as lua\
|
| \(lua expr "vars.thunk.value") as lua\
|
||||||
| return ret
|
| goto finished_when
|
||||||
|end
|
|end
|
||||||
|
%result join=: "\n::finished_when::"
|
||||||
%result
|
%result
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ lua block ".."
|
|||||||
|compiler:defmacro("macro statement %macro_def = %user_macro", make_fn(false), "see:lib/metaprogramming.nom")
|
|compiler:defmacro("macro statement %macro_def = %user_macro", make_fn(false), "see:lib/metaprogramming.nom")
|
||||||
|compiler:defmacro("macro block %macro_def = %user_macro", make_fn(true), "see:lib/metaprogramming.nom")
|
|compiler:defmacro("macro block %macro_def = %user_macro", make_fn(true), "see:lib/metaprogramming.nom")
|
||||||
|
|
||||||
macro block [macro %macro_def = %user_macro] =:
|
macro statement [macro %macro_def = %user_macro] =:
|
||||||
".."|compiler:defmacro(
|
".."|compiler:defmacro(
|
||||||
| \lua expr "compiler:get_aliases(vars.macro_def)"\,
|
| \lua expr "compiler:get_aliases(vars.macro_def)"\,
|
||||||
| \lua expr "compiler:tree_to_lua(vars.user_macro)"\,
|
| \lua expr "compiler:tree_to_lua(vars.user_macro)"\,
|
||||||
@ -60,7 +60,7 @@ macro [compiler utils %method %args] =:
|
|||||||
function calls and convert it into a list of strings (rather than call a function that
|
function calls and convert it into a list of strings (rather than call a function that
|
||||||
is currently in the middle of being defined). Being a macro also allows us to snatch
|
is currently in the middle of being defined). Being a macro also allows us to snatch
|
||||||
the source code and store that
|
the source code and store that
|
||||||
macro block [rule %rule_def = %body] =: ".."
|
macro statement [rule %rule_def = %body] =: ".."
|
||||||
|compiler:def(
|
|compiler:def(
|
||||||
| \compiler "repr" [compiler "get_aliases" [%rule_def]]\,
|
| \compiler "repr" [compiler "get_aliases" [%rule_def]]\,
|
||||||
| \compiler "tree_to_lua" [%body]\,
|
| \compiler "tree_to_lua" [%body]\,
|
||||||
|
@ -4,7 +4,7 @@ require "lib/metaprogramming.nom"
|
|||||||
macro [true, yes] =: "true"
|
macro [true, yes] =: "true"
|
||||||
macro [false, no] =: "false"
|
macro [false, no] =: "false"
|
||||||
macro [nil, null] =: "nil"
|
macro [nil, null] =: "nil"
|
||||||
macro block [nop, pass] =: ""
|
macro statement [nop, pass] =: ""
|
||||||
|
|
||||||
# Ternary operator
|
# Ternary operator
|
||||||
macro [%if_expr if %condition else %else_expr] =:
|
macro [%if_expr if %condition else %else_expr] =:
|
||||||
@ -54,7 +54,6 @@ lua block ".."
|
|||||||
|
|
||||||
# Binary Operators
|
# Binary Operators
|
||||||
lua block ".."
|
lua block ".."
|
||||||
|local function make_binops()
|
|
||||||
|local binops = {"+","-","*","/","<","<=",">",">=","^",{"===","=="},{"!==","~="},"and","or",{"mod","%"}}
|
|local binops = {"+","-","*","/","<","<=",">",">=","^",{"===","=="},{"!==","~="},"and","or",{"mod","%"}}
|
||||||
|for _,op in ipairs(binops) do
|
|for _,op in ipairs(binops) do
|
||||||
| local nomsu_alias = op
|
| local nomsu_alias = op
|
||||||
@ -65,8 +64,6 @@ lua block ".."
|
|||||||
| return "("..compiler:tree_to_lua(vars.a).." "..op.." "..compiler:tree_to_lua(vars.b)..")"
|
| return "("..compiler:tree_to_lua(vars.a).." "..op.." "..compiler:tree_to_lua(vars.b)..")"
|
||||||
| end), [[".."|(\\%a as lua\\ ]]..op..[[ \\%b as lua\\)]])
|
| end), [[".."|(\\%a as lua\\ ]]..op..[[ \\%b as lua\\)]])
|
||||||
|end
|
|end
|
||||||
|end
|
|
||||||
|make_binops()
|
|
||||||
# == and != do equivalence checking, rather than identity checking
|
# == and != do equivalence checking, rather than identity checking
|
||||||
macro [%a == %b] =: ".."|compiler.utils.equivalent(\%a as lua\, \%b as lua\)
|
macro [%a == %b] =: ".."|compiler.utils.equivalent(\%a as lua\, \%b as lua\)
|
||||||
macro [%a != %b] =: ".."|(not compiler.utils.equivalent(\%a as lua\, \%b as lua\))
|
macro [%a != %b] =: ".."|(not compiler.utils.equivalent(\%a as lua\, \%b as lua\))
|
||||||
@ -74,7 +71,7 @@ macro [%a != %b] =: ".."|(not compiler.utils.equivalent(\%a as lua\, \%b as lua\
|
|||||||
# Commutative Operators defined for up to 8 operands
|
# Commutative Operators defined for up to 8 operands
|
||||||
# TODO: work out solution for commutative operators using more clever macros
|
# TODO: work out solution for commutative operators using more clever macros
|
||||||
lua block ".."
|
lua block ".."
|
||||||
|local function make_comops(max_operands)
|
|local max_operands = 8
|
||||||
|local comops = {"+","*","and","or"}
|
|local comops = {"+","*","and","or"}
|
||||||
|for _,_op in ipairs(comops) do
|
|for _,_op in ipairs(comops) do
|
||||||
| local op = _op
|
| local op = _op
|
||||||
@ -90,12 +87,10 @@ lua block ".."
|
|||||||
| end))
|
| end))
|
||||||
| end
|
| end
|
||||||
|end
|
|end
|
||||||
|end
|
|
||||||
|make_comops(8)
|
|
||||||
|
|
||||||
# Chained compairsions (e.g. x < y <= z) are defined up to 3 operands
|
# Chained compairsions (e.g. x < y <= z) are defined up to 3 operands
|
||||||
lua block ".."
|
lua block ".."
|
||||||
|local function chained_comparisons(max_operands)
|
|local max_operands = 3
|
||||||
|for _,chainers in ipairs({{"<","<="},{">",">="}}) do
|
|for _,chainers in ipairs({{"<","<="},{">",">="}}) do
|
||||||
| local function recurse(chainers, chain)
|
| local function recurse(chainers, chain)
|
||||||
# The 1-op versions are already more efficiently defined, and a 0-op version doesnt make sense
|
# The 1-op versions are already more efficiently defined, and a 0-op version doesnt make sense
|
||||||
@ -126,8 +121,6 @@ lua block ".."
|
|||||||
| end
|
| end
|
||||||
| recurse(chainers, {})
|
| recurse(chainers, {})
|
||||||
|end
|
|end
|
||||||
|end
|
|
||||||
|chained_comparisons(3)
|
|
||||||
|
|
||||||
# Unary operators
|
# Unary operators
|
||||||
macro [- %a] =: ".."|-(\%a as lua\)
|
macro [- %a] =: ".."|-(\%a as lua\)
|
||||||
|
@ -27,8 +27,7 @@ macro block [secret %key = %new_value] =:
|
|||||||
| compiler:error("Assignment operation has the wrong type for the right hand side. "
|
| compiler:error("Assignment operation has the wrong type for the right hand side. "
|
||||||
| .."Expected Thunk, but got: "..vars.new_value.type.."\\nMaybe you used '=' instead of '=:'?")
|
| .."Expected Thunk, but got: "..vars.new_value.type.."\\nMaybe you used '=' instead of '=:'?")
|
||||||
|end
|
|end
|
||||||
".."|do
|
".."
|
||||||
|local ret
|
|local ret
|
||||||
|\lua expr "compiler:tree_to_lua(vars.new_value.value)"\
|
|\lua expr "compiler:tree_to_lua(vars.new_value.value)"\
|
||||||
|secrets[\repr (%key's "value")\] = ret
|
|secrets[\repr (%key's "value")\] = ret
|
||||||
|end
|
|
||||||
|
@ -5,16 +5,16 @@ rule [error!, panic!, fail!, abort!] =:
|
|||||||
compiler "error"[]
|
compiler "error"[]
|
||||||
rule [error %msg] =:
|
rule [error %msg] =:
|
||||||
compiler "error"[%msg]
|
compiler "error"[%msg]
|
||||||
macro block [assert %condition] =: ".."
|
macro statement [assert %condition] =: ".."
|
||||||
|if not (\%condition as lua\) then
|
|if not (\%condition as lua\) then
|
||||||
| compiler:error()
|
| compiler:error()
|
||||||
|end
|
|end
|
||||||
macro block [assert %condition %msg] =: ".."
|
macro statement [assert %condition %msg] =: ".."
|
||||||
|if not (\%condition as lua\) then
|
|if not (\%condition as lua\) then
|
||||||
| compiler:error(\%msg as lua\)
|
| compiler:error(\%msg as lua\)
|
||||||
|end
|
|end
|
||||||
|
|
||||||
macro block [show generated lua %block] =: ".."
|
macro statement [show generated lua %block] =: ".."
|
||||||
|compiler:writeln(\lua expr "compiler:repr(compiler:tree_to_lua(vars.block.value))"\)
|
|compiler:writeln(\lua expr "compiler:repr(compiler:tree_to_lua(vars.block.value))"\)
|
||||||
|
|
||||||
|
|
||||||
|
24
nomsu.lua
24
nomsu.lua
@ -427,11 +427,22 @@ do
|
|||||||
return concat(buffer, "\n")
|
return concat(buffer, "\n")
|
||||||
elseif "Thunk" == _exp_0 then
|
elseif "Thunk" == _exp_0 then
|
||||||
assert(tree.value.type == "Block", "Non-block value in Thunk")
|
assert(tree.value.type == "Block", "Non-block value in Thunk")
|
||||||
return [[ (function(compiler, vars)
|
local lua = self:tree_to_lua(tree.value)
|
||||||
|
if #tree.value.value == 1 then
|
||||||
|
do
|
||||||
|
local ret_value = lua:match("^%s*ret = (.*)")
|
||||||
|
if ret_value then
|
||||||
|
return ([[ (function(compiler, vars)
|
||||||
|
return %s
|
||||||
|
end)]]):format(ret_value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ([[ (function(compiler, vars)
|
||||||
local ret
|
local ret
|
||||||
]] .. self:tree_to_lua(tree.value) .. "\n" .. [[ return ret
|
%s
|
||||||
end)
|
return ret
|
||||||
]]
|
end)]]):format(lua)
|
||||||
elseif "Statement" == _exp_0 then
|
elseif "Statement" == _exp_0 then
|
||||||
if tree.value.type == "FunctionCall" then
|
if tree.value.type == "FunctionCall" then
|
||||||
local alias = self:get_alias(tree.value)
|
local alias = self:get_alias(tree.value)
|
||||||
@ -759,7 +770,10 @@ do
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
local lua = self:tree_to_value(vars.lua_code, inner_vars)
|
local lua = self:tree_to_value(vars.lua_code, inner_vars)
|
||||||
return "do\n" .. tostring(lua) .. "\nend", true
|
if not lua:match("^do\n.*\nend$") then
|
||||||
|
lua = "do\n" .. tostring(lua) .. "\nend"
|
||||||
|
end
|
||||||
|
return lua, true
|
||||||
end)
|
end)
|
||||||
self:defmacro("lua expr %lua_code", function(self, vars, kind)
|
self:defmacro("lua expr %lua_code", function(self, vars, kind)
|
||||||
local lua_code = vars.lua_code.value
|
local lua_code = vars.lua_code.value
|
||||||
|
18
nomsu.moon
18
nomsu.moon
@ -318,13 +318,19 @@ class NomsuCompiler
|
|||||||
|
|
||||||
when "Thunk"
|
when "Thunk"
|
||||||
assert tree.value.type == "Block", "Non-block value in Thunk"
|
assert tree.value.type == "Block", "Non-block value in Thunk"
|
||||||
return [[
|
lua = @tree_to_lua(tree.value)
|
||||||
|
if #tree.value.value == 1
|
||||||
|
if ret_value = lua\match("^%s*ret = (.*)")
|
||||||
|
return ([[
|
||||||
|
(function(compiler, vars)
|
||||||
|
return %s
|
||||||
|
end)]])\format(ret_value)
|
||||||
|
return ([[
|
||||||
(function(compiler, vars)
|
(function(compiler, vars)
|
||||||
local ret
|
local ret
|
||||||
]]..@tree_to_lua(tree.value).."\n"..[[
|
%s
|
||||||
return ret
|
return ret
|
||||||
end)
|
end)]])\format(lua)
|
||||||
]]
|
|
||||||
|
|
||||||
when "Statement"
|
when "Statement"
|
||||||
-- This case here is to prevent "ret =" from getting prepended when the macro might not want it
|
-- This case here is to prevent "ret =" from getting prepended when the macro might not want it
|
||||||
@ -543,7 +549,9 @@ class NomsuCompiler
|
|||||||
if kind == "Expression" then error("Expected to be in statement.")
|
if kind == "Expression" then error("Expected to be in statement.")
|
||||||
inner_vars = setmetatable({}, {__index:(_,key)-> "vars[#{repr(key)}]"})
|
inner_vars = setmetatable({}, {__index:(_,key)-> "vars[#{repr(key)}]"})
|
||||||
lua = @tree_to_value(vars.lua_code, inner_vars)
|
lua = @tree_to_value(vars.lua_code, inner_vars)
|
||||||
return "do\n#{lua}\nend", true
|
if not lua\match("^do\n.*\nend$")
|
||||||
|
lua = "do\n#{lua}\nend"
|
||||||
|
return lua, true
|
||||||
|
|
||||||
@defmacro "lua expr %lua_code", (vars, kind)=>
|
@defmacro "lua expr %lua_code", (vars, kind)=>
|
||||||
lua_code = vars.lua_code.value
|
lua_code = vars.lua_code.value
|
||||||
|
Loading…
Reference in New Issue
Block a user