add struct intialization

This commit is contained in:
Luna 2019-08-26 11:59:32 -03:00
parent 19fd9daebf
commit c2499f96c9
5 changed files with 85 additions and 5 deletions

View file

@ -11,6 +11,9 @@ because i can
- `for` is split between `for` and `loop` because my fucking god i cant stand - `for` is split between `for` and `loop` because my fucking god i cant stand
having *four* different variations of `for`. having *four* different variations of `for`.
- struct initialization is with `Struct.{}`, not `Struct{}`, to remove parsing
ambiguities
## how ## how
``` ```

View file

@ -18,6 +18,7 @@ fn main(a int) int {
println(50) println(50)
} }
a && b a && b
a || b a || b
@ -35,10 +36,11 @@ fn main(a int) int {
return 23 return 23
//p := Point{ p := Point.{
// x: 10 x: 10
// y: 20 y: 20
//} }
//println(p.x) //println(p.x)
} }

View file

@ -77,6 +77,8 @@ pub const ExprType = enum {
Literal, Literal,
Variable, Variable,
Call, Call,
Struct,
Grouping, Grouping,
}; };
@ -91,6 +93,18 @@ pub const CallExpr = struct {
arguments: ExprList, arguments: ExprList,
}; };
pub const StructInit = struct {
field: Token,
expr: *Expr,
};
pub const StructInitList = std.ArrayList(StructInit);
pub const StructExpr = struct {
name: Token,
inits: StructInitList,
};
pub const Expr = union(ExprType) { pub const Expr = union(ExprType) {
Assign: AssignExpr, Assign: AssignExpr,
VarDecl: VarDecl, VarDecl: VarDecl,
@ -99,6 +113,7 @@ pub const Expr = union(ExprType) {
Unary: UnaryExpr, Unary: UnaryExpr,
Logical: LogicalExpr, Logical: LogicalExpr,
Literal: LiteralExpr, Literal: LiteralExpr,
Struct: StructExpr,
Variable: Token, Variable: Token,
Grouping: *Expr, Grouping: *Expr,

View file

@ -165,6 +165,18 @@ pub fn printExpr(expr: *Expr) void {
std.debug.warn(")"); std.debug.warn(")");
}, },
.Struct => |val| {
std.debug.warn("({} (", val.name.lexeme);
for (val.inits.toSlice()) |init| {
std.debug.warn(" ({} ", init.field.lexeme);
printExpr(init.expr);
std.debug.warn(")");
}
std.debug.warn("))");
},
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
} }
} }

View file

@ -259,6 +259,18 @@ pub const Parser = struct {
return expr; return expr;
} }
fn mkStructExpr(self: *@This(), name: Token, args: ast.StructInitList) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
.Struct = ast.StructExpr{
.name = name,
.inits = args,
},
};
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{
@ -699,6 +711,9 @@ pub const Parser = struct {
var expr = try self.parsePrimary(); var expr = try self.parsePrimary();
while (true) { while (true) {
std.debug.warn("maybe fncall / struct: {}\n", self.peek().ttype);
printer.printExpr(expr);
if (self.check(.LeftParen)) { if (self.check(.LeftParen)) {
if (ast.ExprType(expr.*) != .Variable) { if (ast.ExprType(expr.*) != .Variable) {
self.doError("cannot call non-variable {}", ast.ExprType(expr.*)); self.doError("cannot call non-variable {}", ast.ExprType(expr.*));
@ -707,6 +722,10 @@ pub const Parser = struct {
_ = try self.consumeSingle(.LeftParen); _ = try self.consumeSingle(.LeftParen);
expr = try self.finishCall(expr); expr = try self.finishCall(expr);
} else if (self.check(.Dot)) {
_ = try self.consumeSingle(.Dot);
_ = try self.consumeSingle(.LeftBrace);
expr = try self.finishStructVal(expr);
} else { } else {
break; break;
} }
@ -738,6 +757,35 @@ pub const Parser = struct {
return self.mkCall(callee, paren, args); return self.mkCall(callee, paren, args);
} }
fn finishStructVal(self: *@This(), expr: *Expr) !*Expr {
// <expr>{a: 10 b: 10}
// for this to work properly, <expr> must be Variable, since its a type.
if (ast.ExprType(expr.*) != .Variable) {
self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*));
return Result.CompileError;
}
var inits = ast.StructInitList.init(self.allocator);
errdefer inits.deinit();
while (!self.check(.RightBrace)) {
const field_name = try self.consumeSingle(.Identifier);
// TODO check .Comma for the quick initialization {val,val,val}
_ = try self.consumeSingle(.Colon);
const field_value = (try self.parseExpr()).Expr;
try inits.append(ast.StructInit{
.field = field_name,
.expr = field_value,
});
}
_ = try self.consumeSingle(.RightBrace);
return try self.mkStructExpr(expr.Variable, inits);
}
fn parsePrimary(self: *@This()) !*Expr { fn parsePrimary(self: *@This()) !*Expr {
const curtype = self.peek().ttype; const curtype = self.peek().ttype;
const lexeme = self.peek().lexeme; const lexeme = self.peek().lexeme;