diff options
author | Manuel Palenzuela Merino <manuel.palenzuela@datadoghq.com> | 2025-01-16 22:10:36 +0100 |
---|---|---|
committer | Manuel Palenzuela Merino <manuel.palenzuela@datadoghq.com> | 2025-01-16 22:10:36 +0100 |
commit | aee5b54b09b72d7478b875ddf77bafb264b1427f (patch) | |
tree | 3f89006b69ef3732cb4d969a03e481666c8e0e61 | |
parent | Evaluator: Start working on new function-capable evaluator (diff) | |
download | interpreter-aee5b54b09b72d7478b875ddf77bafb264b1427f.tar.gz interpreter-aee5b54b09b72d7478b875ddf77bafb264b1427f.tar.bz2 interpreter-aee5b54b09b72d7478b875ddf77bafb264b1427f.zip |
Get function calls kind of working :)
-rw-r--r-- | examples/0.src | 6 | ||||
-rw-r--r-- | examples/1.src | 8 | ||||
-rw-r--r-- | examples/2.src | 10 | ||||
-rw-r--r-- | examples/3.src | 10 | ||||
-rw-r--r-- | src/evaluator.zig | 82 |
5 files changed, 68 insertions, 48 deletions
diff --git a/examples/0.src b/examples/0.src index b87aa0c..8b21f41 100644 --- a/examples/0.src +++ b/examples/0.src @@ -1 +1,5 @@ -print(2); +let main = () => { + print(2); + + return 1; +}; diff --git a/examples/1.src b/examples/1.src index 4c6c73b..cb29345 100644 --- a/examples/1.src +++ b/examples/1.src @@ -1,3 +1,7 @@ -let i = 4; +let main = () => { + let i = 4; -print(i); + print(i); + + return 0; +}; diff --git a/examples/2.src b/examples/2.src index da99740..561d626 100644 --- a/examples/2.src +++ b/examples/2.src @@ -1,5 +1,9 @@ -let test = 1922; +let main = () => { + let test = 1922; -test = 7; + test = 7; -print(test); + print(test); + + return test; +}; diff --git a/examples/3.src b/examples/3.src index 4b56092..49a0a52 100644 --- a/examples/3.src +++ b/examples/3.src @@ -1,5 +1,9 @@ -let seventeen = 10 + 2 + 4; +let main = () => { + let seventeen = 10 + 2 + 4; -seventeen = seventeen + 1; + seventeen = seventeen + 1; -print(seventeen); + print(seventeen); + + return seventeen; +}; diff --git a/src/evaluator.zig b/src/evaluator.zig index 13c7639..6010e3b 100644 --- a/src/evaluator.zig +++ b/src/evaluator.zig @@ -26,15 +26,11 @@ pub const Evaluator = struct { } pub fn evaluate_ast(self: *Evaluator, ast: *parser.Node) !i64 { + errdefer std.debug.print("Error evaluating AST\n", .{}); std.debug.assert(ast.* == parser.Node.PROGRAM); const main = find_main(ast) orelse return EvaluatorError.EvaluationError; - - for (main.*.FUNCTION_DEFINITION.statements) |statement| { - try self.evaluate_statement(statement); - } - - return 0; //TODO: Return value + return try self.evaluate_function_definition(main); } fn evaluate_statement(self: *Evaluator, statement: *parser.Node) EvaluatorError!void { @@ -44,7 +40,7 @@ pub const Evaluator = struct { return switch (statement.STATEMENT.statement.*) { .ASSIGNMENT_STATEMENT => |*assignment_statement| try self.evaluate_assignment_statement(@ptrCast(assignment_statement)), .PRINT_STATEMENT => |*print_statement| try self.evaluate_print_statement(@ptrCast(print_statement)), - .FUNCTION_CALL_STATEMENT => |*function_call_statement| try self.evaluate_function_call_statement(@ptrCast(function_call_statement)), + .FUNCTION_CALL_STATEMENT => |*function_call_statement| _ = try self.evaluate_function_call_statement(@ptrCast(function_call_statement)), else => unreachable, }; } @@ -77,63 +73,71 @@ pub const Evaluator = struct { std.debug.print("PRINT: {d}\n", .{print_value}); } - fn evaluate_function_call_statement(self: *Evaluator, function_call_statement: *parser.Node) !void { + fn evaluate_function_call_statement(self: *Evaluator, function_call_statement: *parser.Node) !i64 { errdefer std.debug.print("Error evaluating function call statement\n", .{}); std.debug.assert(function_call_statement.* == parser.Node.FUNCTION_CALL_STATEMENT); const node = self.variables.get(function_call_statement.FUNCTION_CALL_STATEMENT.name) orelse return EvaluatorError.EvaluationError; - const x = node.?.FUNCTION_DEFINITION; - - for (x.statements) |stmt| { - try self.evaluate_statement(stmt); //TODO: Return stmt? - } + return try self.evaluate_function_definition(node.?); } - // TODO: This is a functionless implementation of return, we should not do this - fn evaluate_return_statement(self: *Evaluator, return_statement: *parser.Node) !void { + fn evaluate_return_statement(self: *Evaluator, return_statement: *parser.Node) !i64 { errdefer std.debug.print("Error evaluating return statement\n", .{}); std.debug.assert(return_statement.* == parser.Node.RETURN_STATEMENT); const return_value = try self.get_expression_value(return_statement.RETURN_STATEMENT.expression); - self.return_value = return_value; + return return_value; } fn get_expression_value(self: *Evaluator, node: *parser.Node) !i64 { errdefer std.debug.print("Error getting statement value\n", .{}); - std.debug.assert(node.* == parser.Node.EXPRESSION); - - switch (node.EXPRESSION) { - .ADDITIVE_EXPRESSION => |additive_expression| { - switch (additive_expression.expression.*) { - .ADDITIVE_EXPRESSION => |x| { - const lhs = try self.get_expression_value(x.lhs); - const rhs = try self.get_expression_value(x.rhs); - return lhs + rhs; - }, - .PRIMARY_EXPRESSION => |x| { - switch (x) { - .NUMBER => |number| return number.value, - .IDENTIFIER => |identifier| { - const val = self.variables.get(identifier.name) orelse { - std.debug.print("Identifier {any} not found\n", .{identifier.name}); - return EvaluatorError.EvaluationError; - }; - - return self.get_expression_value(val.?); - }, - else => unreachable, - } + + switch (node.*) { + .ADDITIVE_EXPRESSION => |x| { + const lhs = try self.get_expression_value(x.lhs); + const rhs = try self.get_expression_value(x.rhs); + return lhs + rhs; + }, + .PRIMARY_EXPRESSION => |x| { + switch (x) { + .NUMBER => |number| return number.value, + .IDENTIFIER => |identifier| { + const val = self.variables.get(identifier.name) orelse { + std.debug.print("Identifier {any} not found\n", .{identifier.name}); + return EvaluatorError.EvaluationError; + }; + + return self.get_expression_value(val.?); }, else => unreachable, } }, + else => unreachable, } } + fn evaluate_function_definition(self: *Evaluator, node: *parser.Node) !i64 { + errdefer std.debug.print("Error evaluating function definition\n", .{}); + std.debug.assert(node.* == parser.Node.FUNCTION_DEFINITION); + + const function_definition = node.*.FUNCTION_DEFINITION; + + var i: usize = 0; + while (i < function_definition.statements.len - 1) { + const stmt = function_definition.statements[i]; + try self.evaluate_statement(stmt); + i += 1; + } + + const return_stmt = function_definition.statements[i]; + return try self.evaluate_return_statement(return_stmt); + } + fn find_main(ast: *parser.Node) ?*parser.Node { + errdefer std.debug.print("Error finding main function\n", .{}); std.debug.assert(ast.* == parser.Node.PROGRAM); for (ast.PROGRAM.statements) |*statement| { |