add function calls

This commit is contained in:
Luna 2019-08-25 22:41:25 -03:00
parent 4f0c43865f
commit 5ba807d93f
3 changed files with 74 additions and 1 deletions

View file

@ -30,4 +30,6 @@ fn main(a int) int {
loop a > 2 { loop a > 2 {
println('skirts') println('skirts')
} }
cock_and_ball_torture('cbt', 1, 2, 3)
} }

View file

@ -76,6 +76,7 @@ pub const ExprType = enum {
Logical, Logical,
Literal, Literal,
Variable, Variable,
Call,
Grouping, Grouping,
}; };
@ -84,6 +85,12 @@ pub const VarDecl = struct {
mutable: bool = false, mutable: bool = false,
}; };
pub const CallExpr = struct {
callee: *Expr,
paren: Token,
arguments: ExprList,
};
pub const Expr = union(ExprType) { pub const Expr = union(ExprType) {
Assign: AssignExpr, Assign: AssignExpr,
VarDecl: VarDecl, VarDecl: VarDecl,
@ -95,6 +102,7 @@ pub const Expr = union(ExprType) {
Variable: Token, Variable: Token,
Grouping: *Expr, Grouping: *Expr,
Call: CallExpr,
}; };
pub const Block = std.ArrayList(*Stmt); pub const Block = std.ArrayList(*Stmt);
@ -305,6 +313,18 @@ pub fn printExpr(expr: *Expr) void {
std.debug.warn(")"); std.debug.warn(")");
}, },
.Call => |call| {
std.debug.warn("(");
printExpr(call.callee);
for (call.arguments.toSlice()) |arg| {
std.debug.warn(" ");
printExpr(arg);
}
std.debug.warn(")");
},
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
} }
} }

View file

@ -241,6 +241,19 @@ pub const Parser = struct {
return vardecl; return vardecl;
} }
fn mkCall(self: *@This(), callee: *Expr, paren: Token, args: ast.ExprList) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
.Call = ast.CallExpr{
.callee = callee,
.paren = paren,
.arguments = 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{
@ -676,10 +689,48 @@ pub const Parser = struct {
return try self.mkUnary(op, right); return try self.mkUnary(op, right);
} }
var expr = try self.parsePrimary(); var expr = try self.parseCall();
return expr; return expr;
} }
fn parseCall(self: *@This()) !*Expr {
var expr = try self.parsePrimary();
while (true) {
if (self.check(.LeftParen)) {
_ = try self.consumeSingle(.LeftParen);
expr = try self.finishCall(expr);
} else {
break;
}
}
return expr;
}
fn finishCall(self: *@This(), callee: *Expr) !*Expr {
var args = ast.ExprList.init(self.allocator);
errdefer args.deinit();
if (!self.check(.RightParen)) {
// emulating do-while really badly
var arg = (try self.parseExpr()).Expr;
try args.append(arg);
while (self.check(.Comma)) {
_ = try self.consumeSingle(.Comma);
arg = (try self.parseExpr()).Expr;
try args.append(arg);
}
}
var paren = try self.consume(.RightParen, "Expected ')' after arguments");
return self.mkCall(callee, paren, args);
}
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;