diff --git a/generator.v b/generator.v index 6df6577..f73c378 100644 --- a/generator.v +++ b/generator.v @@ -112,7 +112,6 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { g.out.writeln('}') } FuncDecl { - dump(stmt.ret_type) c_type := g.mangle_if_class(g.get_c_type(stmt.ret_type)) g.out.write_string('${c_type} ${mangle_func(stmt.name)}(') for param in stmt.params { @@ -121,7 +120,7 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { g.out.write_string(', ') } } - g.out.write_string(')') + g.out.write_string(') ') g.gen_stmt(stmt.block) } Param { @@ -138,6 +137,22 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { g.gen_class_print_func(stmt) } + IfStmt { + g.out.write_string('if (') + g.gen_expr(stmt.condition) + g.out.write_string(') ') + g.gen_stmt(stmt.block) + } + ElseStmt { + g.out.write_string('else ') + g.gen_stmt(stmt.block) + } + ElifStmt { + g.out.write_string('else if (') + g.gen_expr(stmt.condition) + g.out.write_string(') ') + g.gen_stmt(stmt.block) + } } } @@ -173,7 +188,6 @@ fn (mut g Generator) gen_expr(expr Expr) { for i < expr.exprs.len { inner_expr := expr.exprs[i]; expr_type := expr.types[i]; - label := g.get_print_label(inner_expr); if g.symbols.lookup_class(expr_type) != none { class_name := mangle_struct(expr_type) g.out.write_string('print_${class_name}(') @@ -181,7 +195,6 @@ fn (mut g Generator) gen_expr(expr Expr) { g.out.write_string(', 0);') } else { g.out.write_string('printf(\"') - dump(label); format := get_type_format(expr_type) g.out.write_string('%${format}') g.out.write_string('\", ') @@ -193,7 +206,7 @@ fn (mut g Generator) gen_expr(expr Expr) { g.out.write_string('printf(\" \");') } } - g.out.write_string('printf(\"\\n\");\n') + g.out.write_string('printf(\"\\n\")') } TypeCast { c_type := g.mangle_if_class(g.get_c_type(expr.type)) diff --git a/lexer.v b/lexer.v index 347d7ac..944ec05 100644 --- a/lexer.v +++ b/lexer.v @@ -8,6 +8,7 @@ enum TokenType as u8 { type kw_if kw_else + kw_elif kw_for kw_break kw_fn @@ -99,6 +100,7 @@ fn toktype_from_kw(kw string) TokenType { 'void', 'real', 'bool', 'int', 'string'{.type} 'if' {.kw_if} 'else' {.kw_else} + 'elif' {.kw_elif} 'for' {.kw_for} 'break' {.kw_break} 'fn' {.kw_fn} @@ -125,7 +127,7 @@ fn is_real(str string) bool { fn is_keyword(str string) bool { return [ - "void", "int", "real", "bool", "string", "if", "else", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class" + "void", "int", "real", "bool", "string", "if", "else", "elif", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class" ].contains(str) } diff --git a/one b/one index f14621c..775aea3 100755 Binary files a/one and b/one differ diff --git a/parser.v b/parser.v index d7239b5..505d322 100644 --- a/parser.v +++ b/parser.v @@ -16,14 +16,14 @@ enum Precedence { } fn (p Parser) get_precedence(tok_type TokenType) Precedence { - return match tok_type { - .equals, .plus_eq, .minus_eq, .star_eq, .slash_eq { .assignment } - .eq_eq, .not_eq, .less_eq, .greater_eq { .comparison } - .plus, .minus { .sum } - .star, .slash { .product } - .dot { .access } - else { .lowest } - } + return match tok_type { + .equals, .plus_eq, .minus_eq, .star_eq, .slash_eq { .assignment } + .eq_eq, .not_eq, .less_eq, .greater_eq, .less, .greater { .comparison } + .plus, .minus { .sum } + .star, .slash { .product } + .dot { .access } + else { .lowest } + } } // ------------------------------------------- Symbol Table @@ -194,7 +194,7 @@ struct FnCall { // ------------------------------------------- Statements -type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | ClassDecl +type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | IfStmt | ElseStmt | ElifStmt | FuncDecl | Param | ClassDecl struct VarDecl { name string @@ -227,6 +227,20 @@ struct Block { stmts []Stmt } +struct IfStmt { + condition Expr + block Block +} + +struct ElseStmt { + block Block +} + +struct ElifStmt { + condition Expr + block Block +} + struct Param { name string type string @@ -425,11 +439,9 @@ fn (mut p Parser) parse_print() PrintExpr { } fn (mut p Parser) parse_binary(left Expr, op string, prec Precedence) BinaryExpr { - //p.next() right := p.parse_expr(prec) binary_expr := BinaryExpr{left, op, right} - if !p.is_op_valid_for_type(p.get_expr_type(left), op) { parse_error("Illegal operation ${op} for type ${p.get_expr_type(left)}") } @@ -483,7 +495,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string { BinaryExpr { p.check_binary_expr_types(expr) left_t := p.get_expr_type(expr.left) - if expr.op in ['<=', '==', '>=', '!='] { + if expr.op in ['<=', '==', '>=', '!=', '<', '>'] { 'bool' } else { left_t @@ -548,6 +560,9 @@ fn (mut p Parser) parse_statement() Stmt { .kw_fn {return p.parse_func_decl()} .lbracket {return p.parse_block(false)} .kw_class {return p.parse_class()} + .kw_if {return p.parse_if()} + .kw_else {return p.parse_else()} + .kw_elif {return p.parse_elif()} else {return p.parse_expr_stmt()} } } @@ -693,13 +708,42 @@ fn (mut p Parser) parse_return_stmt() ReturnStmt { expr := p.parse_expr(.lowest) - p.next() + p.expect(.semicolon) return ReturnStmt { expr: expr } } +fn (mut p Parser) parse_if() IfStmt { + p.expect(.kw_if) + cond := p.parse_expr(.lowest) + if p.get_expr_type(cond) != 'bool' { + parse_error('If condition must be of type bool') + } + block := p.parse_block(false) + + return IfStmt {cond, block} +} + +fn (mut p Parser) parse_else() ElseStmt { + p.expect(.kw_else) + block := p.parse_block(false) + + return ElseStmt {block} +} + +fn (mut p Parser) parse_elif() ElifStmt { + p.expect(.kw_elif) + cond := p.parse_expr(.lowest) + if p.get_expr_type(cond) != 'bool' { + parse_error('If condition must be of type bool') + } + block := p.parse_block(false) + + return ElifStmt {cond, block} +} + fn (mut p Parser) parse_expr_stmt() ExprStmt { expr := p.parse_expr(.lowest) p.expect(.semicolon) @@ -729,7 +773,6 @@ fn (mut p Parser) parse_block(no_scope bool) Block { p.expect(.rbracket) - return_stmts := (statements.filter(it is ReturnStmt).map(it as ReturnStmt)) if return_stmts.len > 0 && (return_stmts.len > 1 || Stmt(return_stmts[0]) != statements[statements.len - 1]) { parse_error("Unexpected use of return. Unreachable code") diff --git a/v.mod b/v.mod index d22950c..72576fb 100644 --- a/v.mod +++ b/v.mod @@ -1,6 +1,6 @@ Module { - name: 'onev' - description: 'onelang compuler in v' + name: 'one' + description: 'onelang compiler in v' version: '0.0.0' license: 'MIT' dependencies: []