add assignment support (without mut)

This commit is contained in:
Luna 2019-08-25 10:27:50 -03:00
parent 366be14cea
commit 72bc932d23
5 changed files with 57 additions and 8 deletions

View file

@ -9,6 +9,6 @@ fn main(a int) int {
1 + 2 + 3 + 4 1 + 2 + 3 + 4
1 + 1 * 1 1 + 1 * 1
3 / (51 + 2) 3 / (51 + 2)
mut a := 1+2 a := 1+2
println(2 * 1956 + a) println(2 * 1956 + a)
} }

View file

@ -54,7 +54,22 @@ pub const LiteralExpr = union(enum) {
String: []const u8, String: []const u8,
}; };
pub const Expr = union(enum) { pub const AssignExpr = struct {
name: Token,
value: *Expr,
};
pub const ExprType = enum {
Assign,
Binary,
Unary,
Literal,
Variable,
Grouping,
};
pub const Expr = union(ExprType) {
Assign: AssignExpr,
Binary: BinaryExpr, Binary: BinaryExpr,
Unary: UnaryExpr, Unary: UnaryExpr,
Literal: LiteralExpr, Literal: LiteralExpr,
@ -208,6 +223,12 @@ pub fn printExpr(expr: *Expr) void {
.Variable => |token| std.debug.warn("{}", token.lexeme), .Variable => |token| std.debug.warn("{}", token.lexeme),
.Assign => |assign| {
std.debug.warn("(let ");
std.debug.warn("{} ", assign.name.lexeme);
printExpr(assign.value);
},
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
} }
} }

View file

@ -182,8 +182,6 @@ pub const Parser = struct {
} }
fn mkBinary(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr { fn mkBinary(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr {
std.debug.warn("Binary\n");
var expr = try self.allocator.create(Expr); var expr = try self.allocator.create(Expr);
expr.* = Expr{ expr.* = Expr{
.Binary = ast.BinaryExpr{ .Binary = ast.BinaryExpr{
@ -196,6 +194,18 @@ pub const Parser = struct {
return expr; return expr;
} }
fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
.Assign = ast.AssignExpr{
.name = name,
.value = value,
},
};
return expr;
}
fn mkBool(self: *Parser, val: bool) !*ast.Expr { fn mkBool(self: *Parser, val: bool) !*ast.Expr {
var expr = try self.allocator.create(Expr); var expr = try self.allocator.create(Expr);
expr.* = Expr{ expr.* = Expr{
@ -411,7 +421,7 @@ pub const Parser = struct {
var name = try self.consumeSingle(.Identifier); var name = try self.consumeSingle(.Identifier);
_ = try self.consumeSingle(.Assign); _ = try self.consumeSingle(.Equal);
var initializer = (try self.parseExpr()).Expr; var initializer = (try self.parseExpr()).Expr;
return try Stmt.mkVarDecl(self.allocator, name, initializer, true); return try Stmt.mkVarDecl(self.allocator, name, initializer, true);
@ -442,10 +452,28 @@ pub const Parser = struct {
} }
fn parseExpr(self: *@This()) anyerror!*Node { fn parseExpr(self: *@This()) anyerror!*Node {
var expr = try self.parseEquality(); var expr: *Expr = try self.parseAssignment();
return self.mkExpr(expr); return self.mkExpr(expr);
} }
fn parseAssignment(self: *@This()) anyerror!*Expr {
var expr = try self.parseEquality();
if (self.check(.ColonEqual)) {
var op = try self.consumeSingle(.ColonEqual);
var value = try self.parseAssignment();
if (ast.ExprType(expr.*) == .Variable) {
return try self.mkAssign(expr.Variable, value);
}
self.doError("Invalid assignment target");
return Result.CompileError;
}
return expr;
}
fn parseEquality(self: *@This()) !*Expr { fn parseEquality(self: *@This()) !*Expr {
var expr = try self.parseComparison(); var expr = try self.parseComparison();

View file

@ -297,7 +297,7 @@ pub const Scanner = struct {
'*' => self.makeToken(.Star), '*' => self.makeToken(.Star),
'%' => self.makeToken(.Modulo), '%' => self.makeToken(.Modulo),
':' => self.makeMatchToken('=', .Assign, .Colon), ':' => self.makeMatchToken('=', .ColonEqual, .Colon),
'!' => self.makeMatchToken('=', .BangEqual, .Bang), '!' => self.makeMatchToken('=', .BangEqual, .Bang),
'=' => self.makeMatchToken('=', .EqualEqual, .Equal), '=' => self.makeMatchToken('=', .EqualEqual, .Equal),

View file

@ -29,7 +29,7 @@ pub const TokenType = enum {
PlusPlus, PlusPlus,
PlusEqual, PlusEqual,
MinusEqual, MinusEqual,
Assign, ColonEqual,
// comparison ones // comparison ones
EqualEqual, EqualEqual,