diff --git a/parser.v b/parser.v index b0726df..db1fe2f 100644 --- a/parser.v +++ b/parser.v @@ -70,7 +70,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool { // ------------------------------------------- Expressions -type Expr = VoidExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function +type Expr = VoidExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast type LiteralExpr = IntegerLiteral | RealLiteral | BoolLiteral struct VoidExpr {} @@ -105,6 +105,11 @@ struct Function { name string } +struct TypeCast { + expr Expr + type string +} + // ------------------------------------------- Statements type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl @@ -194,8 +199,8 @@ fn (mut p Parser) parse_primary() Expr { .real {RealLiteral{token.text.f32()}} .boolean {BoolLiteral{token.text == 'true'}} .identifier {Variable{token.text}} - .type {TypeExpr{token.text}} .kw_fn {Function{token.text}} + .type {p.parse_type(token.text)} else {parse_error("Unexpected Token")} } } @@ -216,7 +221,27 @@ fn (mut p Parser) parse_expr() Expr { fn (mut p Parser) parse_binary(left Expr, op string) BinaryExpr { p.next() right := p.parse_expr() - return BinaryExpr{left, op, right} + binary_expr := BinaryExpr{left, op, right} + if !p.is_op_valid_for_type(p.get_expr_type(binary_expr), op) { + parse_error("Illegal operation ${op} for type ${p.get_expr_type(binary_expr)}") + } + return binary_expr +} + +fn (mut p Parser) parse_type(type string) Expr { + + if p.peek().type == .lparen { + p.next() + expr := p.parse_expr() + p.expect(.rparen) + + return TypeCast { + expr: expr + type: type + } + } + + return TypeExpr {name: type} } fn (mut p Parser) get_expr_type(expr Expr) string { @@ -240,8 +265,21 @@ fn (mut p Parser) get_expr_type(expr Expr) string { } return info.type } + TypeCast {expr.type} else {"Tried getting type of unexpected Expr"} } + + +} + +fn (mut p Parser) is_op_valid_for_type(type string, op string) bool { + legal_ops := match type { + 'int' {['+', '-', '*', '/', '<', '>', '=']} + 'real' {['+', '-', '*', '/', '<', '>', '=']} + 'bool' {['=']} + else {[]} + } + return op in legal_ops } // ------------------------------------------- Statements @@ -269,6 +307,8 @@ fn (mut p Parser) parse_statement() Stmt { } } + + fn (mut p Parser) parse_var_decl() VarDecl { p.expect(.kw_let) @@ -350,7 +390,6 @@ fn (mut p Parser) parse_return_stmt() ReturnStmt { p.expect(.kw_return) token := p.peek() - p.dump_token() mut expr := Expr{} expr = match token.type { .integer {IntegerLiteral{token.text.int()}} @@ -378,6 +417,7 @@ fn (mut p Parser) parse_expr_stmt() ExprStmt { } } + fn (mut p Parser) parse_block(no_scope bool) Block { p.expect(.lbracket) diff --git a/test.one b/test.one index 383b6d3..3a9582b 100644 --- a/test.one +++ b/test.one @@ -1,9 +1,2 @@ -fn foo() int { - let y int = 2; - let z int = y*2; - return y; -} - -fn bar() real { - return 5.5; -} +let a real = 5.1; +let x real = 7.0 + real(int(a) + int(7.0));