diff --git a/docs/parser.md b/docs/parser.md index 325c471..dd1753d 100644 --- a/docs/parser.md +++ b/docs/parser.md @@ -95,3 +95,35 @@ Now that we have the basic mechanism in place, let's systematically go through t ] } ``` + +## Catch + +```rebo-repl +> rebo.lang.parse("10 catch e -> e") +{ kind: "exprs" +, value: + [ { kind: "catche" + , value: { kind: "literalInt", value: 10 } + , cases: + [ { pattern: { kind: "identifier", value: "e" } + , body: { kind: "identifier", value: "e" } + } + ] + } + ] +} +``` + +## Dot + +```rebo-repl +> rebo.lang.parse("a.b") +{ kind: "exprs" +, value: + [ { kind: "dot" + , record: { kind: "identifier", value: "a" } + , field: "b" + } + ] +} +``` diff --git a/src/ast.zig b/src/ast.zig index 5698ea4..010a687 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -133,16 +133,6 @@ pub const CallExpression = struct { args: []*Expression, }; -pub const IdDeclarationExpression = struct { - name: *SP.String, - value: *Expression, - - pub fn deinit(self: *IdDeclarationExpression, allocator: std.mem.Allocator) void { - self.name.decRef(); - destroyExpr(allocator, self.value); - } -}; - pub const CatchExpression = struct { value: *Expression, cases: []MatchCase, @@ -158,6 +148,16 @@ pub const DotExpression = struct { } }; +pub const IdDeclarationExpression = struct { + name: *SP.String, + value: *Expression, + + pub fn deinit(self: *IdDeclarationExpression, allocator: std.mem.Allocator) void { + self.name.decRef(); + destroyExpr(allocator, self.value); + } +}; + pub const IfCouple = struct { condition: ?*Expression, then: *Expression, diff --git a/src/builtins/parser.zig b/src/builtins/parser.zig index a524c2d..f98174a 100644 --- a/src/builtins/parser.zig +++ b/src/builtins/parser.zig @@ -72,6 +72,49 @@ fn emit(machine: *Helper.Runtime, ast: *AST.Expression, position: bool) !void { } try machine.setRecordItemBang(pos); }, + .catche => { + try machine.pushEmptyRecordValue(); + + try machine.pushStringValue("kind"); + try machine.pushStringValue("catche"); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("value"); + try emit(machine, ast.kind.catche.value, position); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("cases"); + try machine.pushEmptySequenceValue(); + for (ast.kind.catche.cases) |case| { + try machine.pushEmptyRecordValue(); + + try machine.pushStringValue("pattern"); + try emitPattern(machine, case.pattern, position); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("body"); + try emit(machine, case.body, position); + try machine.setRecordItemBang(pos); + + try machine.appendSequenceItemBang(pos); + } + try machine.setRecordItemBang(pos); + }, + .dot => { + try machine.pushEmptyRecordValue(); + + try machine.pushStringValue("kind"); + try machine.pushStringValue("dot"); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("record"); + try emit(machine, ast.kind.dot.record, position); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("field"); + try machine.pushStringValue(ast.kind.dot.field.slice()); + try machine.setRecordItemBang(pos); + }, .exprs => { try machine.pushEmptyRecordValue(); @@ -125,3 +168,33 @@ fn emit(machine: *Helper.Runtime, ast: *AST.Expression, position: bool) !void { try machine.setRecordItemBang(pos); } } + +fn emitPattern(machine: *Helper.Runtime, ast: *AST.Pattern, position: bool) !void { + switch (ast.kind) { + .identifier => { + try machine.pushEmptyRecordValue(); + + try machine.pushStringValue("kind"); + try machine.pushStringValue("identifier"); + try machine.setRecordItemBang(pos); + + try machine.pushStringValue("value"); + try machine.pushStringValue(ast.kind.identifier.slice()); + try machine.setRecordItemBang(pos); + }, + else => { + std.io.getStdErr().writer().print("unreachable: {}\n", .{ast.kind}) catch {}; + unreachable; + }, + } + + if (position) { + try machine.pushStringValue("position"); + try machine.pushEmptySequenceValue(); + try machine.pushIntValue(@intCast(ast.position.start)); + try machine.appendSequenceItemBang(pos); + try machine.pushIntValue(@intCast(ast.position.end)); + try machine.appendSequenceItemBang(pos); + try machine.setRecordItemBang(pos); + } +}