From 45b027e90f0841737b5a1d61e116a0587a32557e Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 26 Aug 2019 13:29:45 -0300 Subject: [PATCH] add assignment to struct fields --- examples/hello.v | 2 ++ src/ast.zig | 9 +++++++++ src/ast_printer.zig | 8 ++++++++ src/parser.zig | 42 ++++++++++++++++++++++++++++++++++-------- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/examples/hello.v b/examples/hello.v index 11f4c7e..9c1f047 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -46,5 +46,7 @@ fn main(a int) int { y: 20 } + p.x = 69 + println(egg.scramble(3).with(cheddar)) } diff --git a/src/ast.zig b/src/ast.zig index acce1d1..c872fd2 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -81,6 +81,7 @@ pub const ExprType = enum { Grouping, Get, + Set, }; pub const VarDecl = struct { @@ -111,6 +112,12 @@ pub const GetExpr = struct { name: Token, }; +pub const SetExpr = struct { + struc: *Expr, + field: Token, + value: *Expr, +}; + pub const Expr = union(ExprType) { Assign: AssignExpr, VarDecl: VarDecl, @@ -124,7 +131,9 @@ pub const Expr = union(ExprType) { Variable: Token, Grouping: *Expr, Call: CallExpr, + Get: GetExpr, + Set: SetExpr, }; pub const Block = std.ArrayList(*Stmt); diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 1574a5b..668e687 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -185,6 +185,14 @@ pub fn printExpr(expr: *Expr) void { warn(".{})", get.name.lexeme); }, + .Set => |set| { + warn("(set "); + printExpr(set.struc); + warn(" {} ", set.field.lexeme); + printExpr(set.value); + warn(")"); + }, + else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), } } diff --git a/src/parser.zig b/src/parser.zig index fb7108e..d3fa8bf 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -287,6 +287,19 @@ pub const Parser = struct { return expr; } + fn mkSet(self: *@This(), struc: *Expr, field: Token, value: *Expr) !*Expr { + var expr = try self.allocator.create(Expr); + expr.* = Expr{ + .Set = ast.SetExpr{ + .struc = struc, + .field = field, + .value = value, + }, + }; + + return expr; + } + fn mkBool(self: *Parser, val: bool) !*ast.Expr { var expr = try self.allocator.create(Expr); expr.* = Expr{ @@ -598,15 +611,28 @@ pub const Parser = struct { _ = try self.nextToken(); value = try self.parseAssignment(); - if (ast.ExprType(expr.*) != .Variable) { - self.doError("Invalid assignment target"); - return Result.CompileError; - } + switch (expr.*) { + .Variable => { + switch (op.ttype) { + .ColonEqual => return try self.mkVarDecl(expr.Variable, value, mutable), + .Equal => return try self.mkAssign(expr.Variable, value), + else => unreachable, + } + }, - switch (op.ttype) { - .ColonEqual => return try self.mkVarDecl(expr.Variable, value, mutable), - .Equal => return try self.mkAssign(expr.Variable, value), - else => unreachable, + .Get => |get| { + if (op.ttype == .ColonEqual) { + self.doError("can not initialize struct field"); + return Result.CompileError; + } + + return try self.mkSet(get.struc, get.name, value); + }, + + else => |expr_typ| { + self.doError("Invalid assignment target {}", expr_typ); + return Result.CompileError; + }, } }