functions with arguments
This commit is contained in:
@@ -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))
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user