Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove half-baked support for method calls #583

Merged
merged 3 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 0 additions & 19 deletions spec/parser_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -744,25 +744,6 @@ describe("Parser /", function()
end)
end)

describe("Method calls without parenthesis", function()

it("for string literals", function()
assert_expression_ast([[ o:m "asd" ]], {
_tag = "ast.Exp.CallMethod",
method = "m",
args = { { _tag = "ast.Exp.String", value = "asd" } }
})
end)

it("for table literals", function()
assert_expression_ast([[ o:m {} ]], {
_tag = "ast.Exp.CallMethod",
method = "m",
args = { { _tag = "ast.Exp.InitList" } }
})
end)
end)

describe("Cast expressions", function()

it("have lower precedence than suffixes", function()
Expand Down
2 changes: 1 addition & 1 deletion src/pallene/assignment_conversion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ function Converter:visit_exp(exp)
elseif tag == "ast.Exp.Lambda" then
self:visit_lambda(exp)

elseif tag == "ast.Exp.CallFunc" or tag == "ast.Exp.CallMethod" then
elseif tag == "ast.Exp.CallFunc" then
self:visit_exp(exp.exp)
for _, arg in ipairs(exp.args) do
self:visit_exp(arg)
Expand Down
3 changes: 1 addition & 2 deletions src/pallene/ast.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ define_union("Stat", {
})

define_union("FuncStat", {
FuncStat = {"loc", "module", "name", "method", "ret_types", "value"},
FuncStat = {"loc", "module", "name", "ret_types", "value"},
})

-- Things that can appear in the LHS of an assignment. For example: x, x[i], x.name
Expand All @@ -65,7 +65,6 @@ define_union("Exp", {
InitList = {"loc", "fields"},
Lambda = {"loc", "arg_decls", "body"},
CallFunc = {"loc", "exp", "args"},
CallMethod = {"loc", "exp", "method", "args"},
Var = {"loc", "var"},
Unop = {"loc", "op", "exp"},
Binop = {"loc", "lhs", "op", "rhs"},
Expand Down
69 changes: 41 additions & 28 deletions src/pallene/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -601,26 +601,43 @@ function Parser:Block()
return ast.Stat.Block(self.prev.loc, self:StatList())
end

function Parser:FuncStat()
function Parser:FuncStat(is_local)
local start = self:e("function")
local root = self:e("NAME").value

local root = self:e("NAME").value

local fields = {}
while self:try(".") do
table.insert(fields, self:e("NAME").value)
end
local field = false
local method = false
if is_local then
if self:peek(".") then
self:syntax_error(self.next.loc, "local function name has a '.'")
self:abort_parsing()
end
if self:peek(":") then
self:syntax_error(self.next.loc, "local function name has a ':'")
self:abort_parsing()
end
else
local fields = {}
while self:try(".") do
table.insert(fields, self:e("NAME").value)
end

if fields[2] then
self:syntax_error(self.prev.loc,
"more than one dot in the function name is not allowed")
end
field = fields[1] or false
if fields[2] then
self:syntax_error(self.prev.loc,
"more than one dot in the function name is not allowed")
end

local field = fields[1] or false
if self:try(":") then
method = self:e("NAME").value
end
end

local method = false
if self:try(":") then
method = self:e("NAME").value
if method then
self:syntax_error(self.prev.loc,
"Pallene does not yet implement method definitions")
self:abort_parsing()
end

local module, name
Expand Down Expand Up @@ -653,7 +670,7 @@ function Parser:FuncStat()
end

return ast.FuncStat.FuncStat(
start.loc, module, name, method, return_types,
start.loc, module, name, return_types,
ast.Exp.Lambda(start.loc, params, block))
end

Expand Down Expand Up @@ -743,13 +760,7 @@ function Parser:Stat()
elseif self:peek("local") then
local start = self:advance()
if self:peek("function") then
local fn = self:FuncStat()
if fn.module then
self:syntax_error(fn.loc, "local function name has a '.'")
end
if fn.method then
self:syntax_error(start.loc, "local function name has a ':'")
end
local fn = self:FuncStat(true)
return ast.Stat.Functions(start.loc, {[fn.name]=true}, {fn})
else
local decls = self:DeclList(); if #decls == 0 then self:forced_syntax_error("NAME") end
Expand All @@ -771,7 +782,7 @@ function Parser:Stat()
return ast.Stat.Return(start.loc, exps)

elseif self:peek("function") then
local fn = self:FuncStat()
local fn = self:FuncStat(false)
return ast.Stat.Functions(fn.loc, {}, {fn})

elseif self:peek(is_primary_exp_first) then
Expand All @@ -787,7 +798,7 @@ function Parser:Stat()
return ast.Stat.Assign(op.loc, lhs, rhs)

else
if exp._tag == "ast.Exp.CallFunc" or exp._tag == "ast.Exp.CallMethod" then
if exp._tag == "ast.Exp.CallFunc" then
return ast.Stat.Call(exp.loc, exp)
else
self:syntax_error(exp.loc,
Expand Down Expand Up @@ -849,10 +860,12 @@ function Parser:SuffixedExp()
exp = ast.Exp.Var(start.loc, ast.Var.Bracket(start.loc, exp, index))

elseif self:peek(":") then
local _ = self:advance()
local id = self:e("NAME")
local args = self:FuncArgs()
exp = ast.Exp.CallMethod(exp.loc, exp, id.value, args)
local _ = self:advance()
local _ = self:e("NAME") -- id
local _ = self:FuncArgs() -- args
self:syntax_error(self.prev.loc,
"Pallene does not yet support method calls")
self:abort_parsing()

elseif self:peek("(") or self:peek("STRING") or self:peek("{") then
local args = self:FuncArgs()
Expand Down
6 changes: 1 addition & 5 deletions src/pallene/to_ir.lua
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ function ToIR:convert_toplevel(prog_ast)

elseif stag == "ast.Stat.Functions" then
for _, func in ipairs(stat.funcs) do
assert(not stat.method)
local f_id = self:register_lambda(func.value, func.name)
if func.module then
n_exports = n_exports + 1
Expand Down Expand Up @@ -920,7 +919,7 @@ function ToIR:exp_to_assignment(cmds, dst, exp)
local use_exp_to_value = false

if not dst then
assert(tag == "ast.Exp.CallFunc" or tag == "ast.Exp.CallMethod")
assert(tag == "ast.Exp.CallFunc")
end

if tag == "ast.Exp.InitList" then
Expand Down Expand Up @@ -1102,9 +1101,6 @@ function ToIR:exp_to_assignment(cmds, dst, exp)
table.insert(cmds, ir.Cmd.CallDyn(loc, f_typ, dsts, f_val, xs))
end

elseif tag == "ast.Exp.CallMethod" then
error("not implemented")

elseif tag == "ast.Exp.Var" then
local var = exp.var
if var._tag == "ast.Var.Name" then
Expand Down
15 changes: 2 additions & 13 deletions src/pallene/typechecker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ end
function Typechecker:expand_function_returns(rhs)
local N = #rhs
local last = rhs[N]
if last and (last._tag == "ast.Exp.CallFunc" or last._tag == "ast.Exp.CallMethod") then
if last and (last._tag == "ast.Exp.CallFunc") then
last = self:check_exp_synthesize(last)
rhs[N] = last
for i = 2, #last._types do
Expand Down Expand Up @@ -572,10 +572,6 @@ function Typechecker:check_stat(stat, is_toplevel)

local typ = types.T.Function(arg_types, ret_types)

if func.method then -- not yet implemented
type_error(func.loc, "method syntax has not been implemented in Pallene yet")
end

if func.module then
-- Module function
local sym = self.symbol_table:find_symbol(func.module)
Expand Down Expand Up @@ -747,11 +743,7 @@ end
-- If the function returns 0 arguments, it is only allowed in a statement context.
-- Void functions in an expression context are a constant source of headaches.
function Typechecker:check_fun_call(exp, is_stat)
assert(exp._tag == "ast.Exp.CallFunc" or exp._tag == "ast.Exp.CallMethod")

if exp._tag == "ast.Exp.CallMethod" then -- not yet implemented
type_error(exp.loc, "method syntax has not been implemented in Pallene yet")
end
assert(exp._tag == "ast.Exp.CallFunc")

exp.exp = self:check_exp_synthesize(exp.exp)

Expand Down Expand Up @@ -970,9 +962,6 @@ function Typechecker:check_exp_synthesize(exp)
elseif tag == "ast.Exp.CallFunc" then
exp = self:check_fun_call(exp, false)

elseif tag == "ast.Exp.CallMethod" then
error("not implemented")

elseif tag == "ast.Exp.Cast" then
exp._type = self:from_ast_type(exp.target)
exp.exp = self:check_exp_verify(exp.exp, exp._type, "cast expression")
Expand Down