parser: split into finishAssignment

This commit is contained in:
Luna 2019-08-26 15:19:31 -03:00
parent c3f0b4b4d5
commit 9e32ff9e16

View file

@ -533,7 +533,7 @@ pub const Parser = struct {
var expr: ?*Expr = null; var expr: ?*Expr = null;
var body: ast.Block = undefined; var body: ast.Block = undefined;
// infinite loop // 'loop {' = infinite loop
if (self.check(.LeftBrace)) { if (self.check(.LeftBrace)) {
body = try self.parseStmtBlock(); body = try self.parseStmtBlock();
} else { } else {
@ -570,7 +570,7 @@ pub const Parser = struct {
} }
fn parseAssignment(self: *@This()) anyerror!*Expr { fn parseAssignment(self: *@This()) anyerror!*Expr {
// there can be two types coming out of this function: // there can be two assignments coming out of this function:
// - a mutable/immutable variable declaration with := // - a mutable/immutable variable declaration with :=
// - an assignment to a variable with = // - an assignment to a variable with =
@ -578,53 +578,50 @@ pub const Parser = struct {
// of this is an Expr, we wrap variable assignments in an Expr as well. // of this is an Expr, we wrap variable assignments in an Expr as well.
var mutable: bool = false; var mutable: bool = false;
std.debug.warn("start assignment pass with cur={}\n", self.peek());
if (self.check(.Mut)) { if (self.check(.Mut)) {
_ = try self.consumeSingle(.Mut); _ = try self.consumeSingle(.Mut);
mutable = true; mutable = true;
} }
var expr = try self.parseOr(); var expr = try self.parseOr();
std.debug.warn("lvalue: {}, cur: {}\n", expr, self.peek());
var value: *Expr = undefined;
var op: Token = undefined;
if (self.check(.ColonEqual) or self.check(.Equal)) { if (self.check(.ColonEqual) or self.check(.Equal)) {
op = self.peek(); return try self.finishAssignment(expr, mutable);
_ = try self.nextToken();
value = try self.parseAssignment();
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,
}
},
.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;
},
}
} }
return expr; return expr;
} }
fn finishAssignment(self: *@This(), expr: *Expr, mutable: bool) !*Expr {
var op = self.peek();
_ = try self.nextToken();
var value = try self.parseAssignment();
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,
}
},
.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;
},
}
}
fn parseOr(self: *@This()) !*Expr { fn parseOr(self: *@This()) !*Expr {
var expr = try self.parseAnd(); var expr = try self.parseAnd();