add assignment to struct fields

This commit is contained in:
Luna 2019-08-26 13:29:45 -03:00
parent d55137a7c7
commit 45b027e90f
4 changed files with 53 additions and 8 deletions

View file

@ -46,5 +46,7 @@ fn main(a int) int {
y: 20
}
p.x = 69
println(egg.scramble(3).with(cheddar))
}

View file

@ -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);

View file

@ -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.*)),
}
}

View file

@ -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;
},
}
}