change variable declarations to statements

doing them as expressions was a hack since no 'var' keyword,
also, yeet the := operator from the parser.
This commit is contained in:
Luna 2019-09-25 22:22:13 -03:00
parent e69451cdd9
commit 45275d73db
7 changed files with 44 additions and 47 deletions

View file

@ -1,6 +1,7 @@
// import std;
fn f() i32 {
var a = 2;
return 2;
}

View file

@ -97,9 +97,6 @@ pub const AssignExpr = struct {
pub const ExprType = enum {
Assign,
// vardecls as expressions is a hack
VarDecl,
Binary,
Unary,
Literal,
@ -112,11 +109,6 @@ pub const ExprType = enum {
Set,
};
pub const VarDecl = struct {
assign: AssignExpr,
mutable: bool = false,
};
pub const CallExpr = struct {
callee: *Expr,
paren: Token,
@ -148,7 +140,6 @@ pub const SetExpr = struct {
pub const Expr = union(ExprType) {
Assign: AssignExpr,
VarDecl: VarDecl,
Binary: BinaryExpr,
Unary: UnaryExpr,
@ -181,10 +172,16 @@ pub const ForStmt = struct {
block: Block,
};
pub const VarDeclStmt = struct {
name: Token,
value: *Expr,
};
pub const Stmt = union(enum) {
Expr: *Expr,
Println: *Expr,
VarDecl: VarDeclStmt,
If: IfStmt,
Loop: LoopStmt,
For: ForStmt,
@ -261,6 +258,18 @@ pub const Stmt = union(enum) {
return stmt;
}
pub fn mkVarDecl(allocator: *std.mem.Allocator, name: Token, value: *Expr) !*Stmt {
var stmt = try allocator.create(Stmt);
stmt.* = Stmt{
.VarDecl = VarDeclStmt{
.name = name,
.value = value,
},
};
return stmt;
}
};
pub const FieldList = std.ArrayList(StructField);

View file

@ -239,18 +239,6 @@ pub fn printExpr(expr: *const Expr) void {
.Variable => |token| std.debug.warn("{}", token.lexeme),
.VarDecl => |decl| {
if (decl.mutable) {
std.debug.warn("(mut ");
} else {
std.debug.warn("(");
}
std.debug.warn("let {} ", decl.assign.name.lexeme);
printExpr(decl.assign.value);
std.debug.warn(")");
},
.Assign => |assign| {
std.debug.warn("(set ");
std.debug.warn("{} ", assign.name.lexeme);
@ -305,6 +293,12 @@ pub fn printStmt(ident: usize, stmt: *const Stmt) void {
.Println => |expr| printSimpleOp("println", expr),
.Expr => |expr| printExpr(expr),
.VarDecl => |decl| {
std.debug.warn("(let {} ", decl.name.lexeme);
printExpr(decl.value);
std.debug.warn(")");
},
.If => |ifstmt| {
std.debug.warn("(if ");
printExpr(ifstmt.condition);

View file

@ -79,8 +79,6 @@ pub const Codegen = struct {
// TODO VarDecl add things to the symbol table
// TODO Assign modify symbol table
// TODO Calls fetch symbol table, check arity of it at codegen level
return switch (expr.*) {
// TODO handle all literals, construct llvm values for them
@ -168,7 +166,6 @@ pub const Codegen = struct {
.Call => |call| {
const name = call.callee.*.Variable.lexeme;
//var sym = try self.ctx.fetchGlobalSymbol(func_name, .Function);
var llvm_func = self.llvm_table.get(name);
if (llvm_func == null) {
@ -176,7 +173,6 @@ pub const Codegen = struct {
return CompileError.EmitError;
}
// TODO args
var args = LLVMValueList.init(self.allocator);
errdefer args.deinit();
@ -342,7 +338,6 @@ pub const Codegen = struct {
llvm.LLVMPositionBuilderAtEnd(builder, entry);
for (decl.body.toSlice()) |stmt| {
// TODO custom function context for us
try self.emitStmt(builder, &stmt);
}

View file

@ -295,21 +295,6 @@ pub const Parser = struct {
return expr;
}
fn mkVarDecl(self: *@This(), name: Token, value: *Expr, mutable: bool) !*Expr {
var vardecl = try self.allocator.create(Expr);
vardecl.* = Expr{
.VarDecl = ast.VarDecl{
.assign = ast.AssignExpr{
.name = name,
.value = value,
},
.mutable = mutable,
},
};
return vardecl;
}
fn mkCall(self: *@This(), callee: *Expr, paren: Token, args: ast.ExprList) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
@ -716,6 +701,7 @@ pub const Parser = struct {
fn parseStmt(self: *@This()) anyerror!*Stmt {
return switch (self.peek().typ) {
.Var => try self.parseVarDecl(),
.If => try self.parseIfStmt(),
.Loop => try self.parseLoop(),
.For => try self.parseForStmt(),
@ -725,6 +711,14 @@ pub const Parser = struct {
};
}
fn parseVarDecl(self: *@This()) !*Stmt {
_ = try self.consumeSingle(.Var);
var name = try self.consumeSingle(.Identifier);
_ = try self.consumeSingle(.Equal);
var value = try self.parseExpr();
return try Stmt.mkVarDecl(self.allocator, name, value);
}
/// Parse a list of statements.
fn parseBlock(self: *@This()) !*Node {
var stmts = try self.parseBlockInternal(ast.StmtList);
@ -840,8 +834,8 @@ pub const Parser = struct {
fn parseAssignment(self: *@This()) anyerror!*Expr {
// there can be two assignments coming out of this function:
// - a mutable/immutable variable declaration with :=
// - an assignment to a variable with =, +=, -=
// - an assignment to a variable with =
// - an update to a variable with +=, -=
// one is a statement, other is an expression. since the normal result
// of this is an Expr, we wrap variable assignments in an Expr as well.
@ -855,7 +849,7 @@ pub const Parser = struct {
var expr = try self.parseOr();
if (self.compareAnyOf(&[_]TokenType{
.ColonEqual, .Equal, .PlusEqual, .MinusEqual, .StarEqual,
.Equal, .PlusEqual, .MinusEqual, .StarEqual,
.SlashEqual,
})) {
return try self.finishAssignment(expr, mutable);
@ -871,8 +865,7 @@ pub const Parser = struct {
var value = try self.parseAssignment();
// expr can be a (Variable|Set)
// op_tok can be one of three categories:
// - ColonEqual, parses to VarDecl (only when expr = Variable)
// op_tok can be one of two categories:
// - Equal, parses to (Assign|Set)
// - Inplace (+=, -=, *=, /=), parses to (Assign|Set)
@ -893,7 +886,6 @@ pub const Parser = struct {
switch (expr.*) {
.Variable => {
switch (op_tok.typ) {
.ColonEqual => return try self.mkVarDecl(expr.Variable, value, mutable),
.Equal => return try self.mkAssign(expr.Variable, value),
.PlusEqual, .MinusEqual, .StarEqual, .SlashEqual => {
@ -909,6 +901,7 @@ pub const Parser = struct {
.Get => |get| {
switch (op_tok.typ) {
// TODO remove .ColonEqual from language
.ColonEqual => {
return self.doError("can not initialize struct field");
},

View file

@ -54,6 +54,7 @@ const keywords = [_][]const u8{
"pub",
"and",
"or",
"var",
};
const keyword_ttypes = [_]TokenType{
@ -86,9 +87,12 @@ const keyword_ttypes = [_]TokenType{
.Pub,
.And,
.Or,
.Var,
};
fn getKeyword(keyword: []const u8) ?TokenType {
std.debug.assert(keywords.len == keyword_ttypes.len);
for (keywords) |kw, idx| {
if (std.mem.eql(u8, keyword, kw)) {
return keyword_ttypes[idx];

View file

@ -77,6 +77,7 @@ pub const TokenType = enum {
Println,
Pub,
Var,
EOF,
};