diff --git a/debug/app.ona b/debug/app.ona index f787fc7..48b8ee8 100644 --- a/debug/app.ona +++ b/debug/app.ona @@ -1,5 +1,5 @@ -i = 0 +var i = 0 while i < 5: @print("hello, world") diff --git a/source/ona/kym.zig b/source/ona/kym.zig index 59803b9..c30c806 100644 --- a/source/ona/kym.zig +++ b/source/ona/kym.zig @@ -213,16 +213,11 @@ pub const RuntimeEnv = struct { .local_set => |local_set| { try self.compile_expression(chunk, local_set.value_expression.*); - if (self.resolve_local(local_set.identifier)) |index| { - try chunk.opcodes.push_one(.{.local_set = index}); - } else { - if (self.local_identifiers_count == self.local_identifiers_buffer.len) { - return chunk.env.raise(error.BadSyntax, "chunks may have a maximum of 255 locals"); - } - - self.local_identifiers_buffer[self.local_identifiers_count] = local_set.identifier; - self.local_identifiers_count += 1; - } + try chunk.opcodes.push_one(.{ + .local_set = self.resolve_local(local_set.identifier) orelse { + return chunk.env.raise(error.BadSyntax, "undefined local"); + }, + }); }, .field_get => |field_get| { @@ -271,6 +266,17 @@ pub const RuntimeEnv = struct { } }, + .local_var => |local_var| { + try self.compile_expression(chunk, local_var.assigned_expression); + + if (self.local_identifiers_count == self.local_identifiers_buffer.len) { + return chunk.env.raise(error.BadSyntax, "chunks may have a maximum of 255 locals"); + } + + self.local_identifiers_buffer[self.local_identifiers_count] = local_var.identifier; + self.local_identifiers_count += 1; + }, + .block => |block| { for (block.values) |block_statement| { try self.compile_statement(chunk, block_statement); diff --git a/source/ona/kym/ast.zig b/source/ona/kym/ast.zig index 9afb040..dc347a3 100644 --- a/source/ona/kym/ast.zig +++ b/source/ona/kym/ast.zig @@ -139,6 +139,11 @@ pub const ParseError = error { pub const Statement = union (enum) { @"return": ?Expression, + local_var: struct { + identifier: []const coral.io.Byte, + assigned_expression: Expression, + }, + @"if": struct { condition_expression: Expression, block_statements: List, @@ -650,6 +655,30 @@ pub const Tree = struct { }; }, + .keyword_var => { + self.tokenizer.skip_newlines(); + + const identifier = switch (self.tokenizer.token) { + .identifier => |identifier| identifier, + else => return self.report("expected identifier after `var` declaration statement"), + }; + + self.tokenizer.skip_newlines(); + + if (self.tokenizer.token != .symbol_equals) { + return self.report("expected `=` after declaration identifier"); + } + + self.tokenizer.skip_newlines(); + + return .{ + .local_var = .{ + .assigned_expression = try self.parse_expression(), + .identifier = identifier, + }, + }; + }, + .keyword_if => return self.parse_branch(), else => return .{.expression = try self.parse_expression()}, } diff --git a/source/ona/kym/tokens.zig b/source/ona/kym/tokens.zig index 3869cf1..2ff609d 100755 --- a/source/ona/kym/tokens.zig +++ b/source/ona/kym/tokens.zig @@ -44,6 +44,7 @@ pub const Token = union(enum) { keyword_while, keyword_else, keyword_elif, + keyword_var, pub fn text(self: Token) []const coral.io.Byte { return switch (self) { @@ -91,6 +92,7 @@ pub const Token = union(enum) { .keyword_while => "while", .keyword_elif => "elif", .keyword_else => "else", + .keyword_var => "var", }; } }; @@ -261,6 +263,14 @@ pub const Tokenizer = struct { } }, + 'v' => { + if (coral.io.ends_with(identifier, "ar")) { + self.token = .keyword_var; + + return; + } + }, + 'w' => { if (coral.io.ends_with(identifier, "hile")) { self.token = .keyword_while;