Compare commits

..

No commits in common. "0e26b8acde04c040233cef58b2257a72873b17ba" and "1e3f676698f88d5e688f28ef80e3b9cdd3d3c5e5" have entirely different histories.

4 changed files with 18 additions and 132 deletions

View File

@ -1,5 +1,5 @@
var i = 0 i = 0
while i < 5: while i < 5:
@print("hello, world") @print("hello, world")

View File

@ -70,18 +70,8 @@ pub const RuntimeEnv = struct {
const OpcodeList = coral.list.Stack(Opcode); const OpcodeList = coral.list.Stack(Opcode);
const CompilationUnit = struct { const CompilationUnit = struct {
locals_buffer: [255]Local = [_]Local{.{}} ** 255, local_identifiers_buffer: [255][]const coral.io.Byte = [_][]const coral.io.Byte{""} ** 255,
locals_count: u8 = 0, local_identifiers_count: u8 = 0,
const ResolvedLocal = struct {
index: u8,
is_readonly: bool = false,
};
const Local = struct {
identifier: []const coral.io.Byte = "",
is_readonly: bool = false,
};
fn compile_expression(self: *CompilationUnit, chunk: *Chunk, expression: ast.Expression) RuntimeError!void { fn compile_expression(self: *CompilationUnit, chunk: *Chunk, expression: ast.Expression) RuntimeError!void {
const number_format = coral.utf8.DecimalFormat{ const number_format = coral.utf8.DecimalFormat{
@ -214,24 +204,25 @@ pub const RuntimeEnv = struct {
.local_get => |local_get| { .local_get => |local_get| {
try chunk.opcodes.push_one(.{ try chunk.opcodes.push_one(.{
.push_local = (self.resolve_local(local_get.identifier) orelse { .push_local = self.resolve_local(local_get.identifier) orelse {
return chunk.env.raise(error.OutOfMemory, "undefined local"); return chunk.env.raise(error.OutOfMemory, "undefined local");
}).index, },
}); });
}, },
.local_set => |local_set| { .local_set => |local_set| {
try self.compile_expression(chunk, local_set.value_expression.*); try self.compile_expression(chunk, local_set.value_expression.*);
const resolved_local = self.resolve_local(local_set.identifier) orelse { if (self.resolve_local(local_set.identifier)) |index| {
return chunk.env.raise(error.BadSyntax, "undefined local"); try chunk.opcodes.push_one(.{.local_set = index});
}; } else {
if (self.local_identifiers_count == self.local_identifiers_buffer.len) {
if (resolved_local.is_readonly) { return chunk.env.raise(error.BadSyntax, "chunks may have a maximum of 255 locals");
return chunk.env.raise(error.BadSyntax, "cannot set a read-only declaration");
} }
try chunk.opcodes.push_one(.{.local_set = resolved_local.index}); self.local_identifiers_buffer[self.local_identifiers_count] = local_set.identifier;
self.local_identifiers_count += 1;
}
}, },
.field_get => |field_get| { .field_get => |field_get| {
@ -280,25 +271,6 @@ pub const RuntimeEnv = struct {
} }
}, },
.declare => |declare| {
if (self.resolve_local(declare.identifier) != null) {
return chunk.env.raise(error.BadSyntax, "declaration shadows existing one");
}
try self.compile_expression(chunk, declare.assigned_expression);
if (self.locals_count == self.locals_buffer.len) {
return chunk.env.raise(error.BadSyntax, "chunks may have a maximum of 255 locals");
}
self.locals_buffer[self.locals_count] = .{
.identifier = declare.identifier,
.is_readonly = declare.storage != .variant,
};
self.locals_count += 1;
},
.block => |block| { .block => |block| {
for (block.values) |block_statement| { for (block.values) |block_statement| {
try self.compile_statement(chunk, block_statement); try self.compile_statement(chunk, block_statement);
@ -348,21 +320,16 @@ pub const RuntimeEnv = struct {
} }
} }
fn resolve_local(self: *CompilationUnit, local_identifier: []const coral.io.Byte) ?ResolvedLocal { fn resolve_local(self: *CompilationUnit, local_identifier: []const coral.io.Byte) ?u8 {
if (self.locals_count == 0) { if (self.local_identifiers_count == 0) {
return null; return null;
} }
var index = @as(u8, self.locals_count - 1); var index = @as(u8, self.local_identifiers_count - 1);
while (true) : (index -= 1) { while (true) : (index -= 1) {
const local = &self.locals_buffer[index]; if (coral.io.are_equal(local_identifier, self.local_identifiers_buffer[index])) {
return index;
if (coral.io.are_equal(local_identifier, local.identifier)) {
return .{
.index = index,
.is_readonly = local.is_readonly,
};
} }
if (index == 0) { if (index == 0) {

View File

@ -129,11 +129,6 @@ pub const Expression = union (enum) {
}); });
}; };
pub const DeclarationStorage = enum {
variant,
readonly,
};
const ExpressionBuilder = fn (self: *Tree) ParseError!Expression; const ExpressionBuilder = fn (self: *Tree) ParseError!Expression;
pub const ParseError = error { pub const ParseError = error {
@ -144,12 +139,6 @@ pub const ParseError = error {
pub const Statement = union (enum) { pub const Statement = union (enum) {
@"return": ?Expression, @"return": ?Expression,
declare: struct {
storage: DeclarationStorage,
identifier: []const coral.io.Byte,
assigned_expression: Expression,
},
@"if": struct { @"if": struct {
condition_expression: Expression, condition_expression: Expression,
block_statements: List, block_statements: List,
@ -661,56 +650,6 @@ 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 .{
.declare = .{
.assigned_expression = try self.parse_expression(),
.storage = .variant,
.identifier = identifier,
},
};
},
.keyword_let => {
self.tokenizer.skip_newlines();
const identifier = switch (self.tokenizer.token) {
.identifier => |identifier| identifier,
else => return self.report("expected identifier after `let` declaration statement"),
};
self.tokenizer.skip_newlines();
if (self.tokenizer.token != .symbol_equals) {
return self.report("expected `=` after declaration identifier");
}
self.tokenizer.skip_newlines();
return .{
.declare = .{
.assigned_expression = try self.parse_expression(),
.storage = .readonly,
.identifier = identifier,
},
};
},
.keyword_if => return self.parse_branch(), .keyword_if => return self.parse_branch(),
else => return .{.expression = try self.parse_expression()}, else => return .{.expression = try self.parse_expression()},
} }

View File

@ -44,8 +44,6 @@ pub const Token = union(enum) {
keyword_while, keyword_while,
keyword_else, keyword_else,
keyword_elif, keyword_elif,
keyword_var,
keyword_let,
pub fn text(self: Token) []const coral.io.Byte { pub fn text(self: Token) []const coral.io.Byte {
return switch (self) { return switch (self) {
@ -93,8 +91,6 @@ pub const Token = union(enum) {
.keyword_while => "while", .keyword_while => "while",
.keyword_elif => "elif", .keyword_elif => "elif",
.keyword_else => "else", .keyword_else => "else",
.keyword_var => "var",
.keyword_let => "let",
}; };
} }
}; };
@ -233,14 +229,6 @@ pub const Tokenizer = struct {
} }
}, },
'l' => {
if (coral.io.ends_with(identifier, "et")) {
self.token = .keyword_let;
return;
}
},
'n' => { 'n' => {
if (coral.io.ends_with(identifier, "il")) { if (coral.io.ends_with(identifier, "il")) {
self.token = .keyword_nil; self.token = .keyword_nil;
@ -273,14 +261,6 @@ pub const Tokenizer = struct {
} }
}, },
'v' => {
if (coral.io.ends_with(identifier, "ar")) {
self.token = .keyword_var;
return;
}
},
'w' => { 'w' => {
if (coral.io.ends_with(identifier, "hile")) { if (coral.io.ends_with(identifier, "hile")) {
self.token = .keyword_while; self.token = .keyword_while;