functions with arguments
Some checks failed
Build / build (push) Failing after 22s
Test / build (push) Failing after 22s

This commit is contained in:
Chuck Smith
2024-03-12 15:53:35 -04:00
parent ec9a586f7f
commit 1d2c7f0a51
6 changed files with 203 additions and 13 deletions

View File

@@ -265,6 +265,10 @@ func (c *Compiler) Compile(node ast.Node) error {
case *ast.FunctionLiteral:
c.enterScope()
for _, p := range node.Parameters {
c.symbolTable.Define(p.Value)
}
err := c.Compile(node.Body)
if err != nil {
return err
@@ -280,7 +284,11 @@ func (c *Compiler) Compile(node ast.Node) error {
numLocals := c.symbolTable.numDefinitions
instructions := c.leaveScope()
compiledFn := &object.CompiledFunction{Instructions: instructions, NumLocals: numLocals}
compiledFn := &object.CompiledFunction{
Instructions: instructions,
NumLocals: numLocals,
NumParameters: len(node.Parameters),
}
c.emit(code.OpConstant, c.addConstant(compiledFn))
case *ast.ReturnStatement:
@@ -297,7 +305,14 @@ func (c *Compiler) Compile(node ast.Node) error {
return err
}
c.emit(code.OpCall)
for _, a := range node.Arguments {
err := c.Compile(a)
if err != nil {
return err
}
}
c.emit(code.OpCall, len(node.Arguments))
}

View File

@@ -562,7 +562,7 @@ func TestFunctionCalls(t *testing.T) {
},
expectedInstructions: []code.Instructions{
code.Make(code.OpConstant, 1), // The compiled function
code.Make(code.OpCall),
code.Make(code.OpCall, 0),
code.Make(code.OpPop),
},
},
@@ -582,7 +582,57 @@ func TestFunctionCalls(t *testing.T) {
code.Make(code.OpConstant, 1), // The compiled function
code.Make(code.OpSetGlobal, 0),
code.Make(code.OpGetGlobal, 0),
code.Make(code.OpCall),
code.Make(code.OpCall, 0),
code.Make(code.OpPop),
},
},
{
input: `
let oneArg = fn(a) { a };
oneArg(24);
`,
expectedConstants: []interface{}{
[]code.Instructions{
code.Make(code.OpGetLocal, 0),
code.Make(code.OpReturnValue),
},
24,
},
expectedInstructions: []code.Instructions{
code.Make(code.OpConstant, 0),
code.Make(code.OpSetGlobal, 0),
code.Make(code.OpGetGlobal, 0),
code.Make(code.OpConstant, 1),
code.Make(code.OpCall, 1),
code.Make(code.OpPop),
},
},
{
input: `
let manyArg = fn(a, b, c) { a; b; c };
manyArg(24, 25, 26);
`,
expectedConstants: []interface{}{
[]code.Instructions{
code.Make(code.OpGetLocal, 0),
code.Make(code.OpPop),
code.Make(code.OpGetLocal, 1),
code.Make(code.OpPop),
code.Make(code.OpGetLocal, 2),
code.Make(code.OpReturnValue),
},
24,
25,
26,
},
expectedInstructions: []code.Instructions{
code.Make(code.OpConstant, 0),
code.Make(code.OpSetGlobal, 0),
code.Make(code.OpGetGlobal, 0),
code.Make(code.OpConstant, 1),
code.Make(code.OpConstant, 2),
code.Make(code.OpConstant, 3),
code.Make(code.OpCall, 3),
code.Make(code.OpPop),
},
},