diff --git a/generator.v b/generator.v index cd7495b..cf20f27 100644 --- a/generator.v +++ b/generator.v @@ -8,6 +8,10 @@ mut: out strings.Builder } +fn mangle_var(name string, scope_depth int) string { + return 'v${name}${scope_depth.str()}' +} + fn (mut g Generator) get_c_type(typ string) string { c_type := if typ == 'real' { 'double' } else { typ } return c_type @@ -17,7 +21,7 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { match stmt { VarDecl { c_type := g.get_c_type(stmt.type) - g.out.write_string('${c_type} v${stmt.name}${stmt.scope_depth.str()} = ') + g.out.write_string('${c_type} ${mangle_var(stmt.name, stmt.scope_depth)} = ') g.gen_expr(stmt.value) g.out.writeln(';') } @@ -39,9 +43,20 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { } FuncDecl { c_type := g.get_c_type(stmt.ret_type) - g.out.write_string('${c_type} ${stmt.name}() ') + g.out.write_string('${c_type} ${stmt.name}(') + for param in stmt.params { + g.gen_stmt(param) + if param != stmt.params[stmt.params.len-1]{ + g.out.write_string(', ') + } + } + g.out.write_string(')') g.gen_stmt(stmt.block) } + Param { + c_type := g.get_c_type(stmt.type) + g.out.write_string('${c_type} ${mangle_var(stmt.name, 2)}') + } } } @@ -57,7 +72,7 @@ fn (mut g Generator) gen_expr(expr Expr) { g.out.write_string(expr.val.str()) } Variable { - g.out.write_string('v${expr.name}${expr.scope_depth.str()}') + g.out.write_string(mangle_var(expr.name, expr.scope_depth)) } UnaryExpr { g.out.write_string('${expr.ident}${expr.op}') @@ -91,7 +106,14 @@ fn (mut g Generator) gen_expr(expr Expr) { g.out.write_string(')') } FnCall { - g.out.write_string('${expr.name}()') + g.out.write_string('${expr.name}(') + for arg in expr.args { + g.gen_expr(arg) + if arg != expr.args[expr.args.len-1]{ + g.out.write_string(', ') + } + } + g.out.write_string(')') } else {panic("Unimplemented expression")} } diff --git a/parser.v b/parser.v index ad19de7..0b24fb2 100644 --- a/parser.v +++ b/parser.v @@ -147,11 +147,12 @@ struct PrintExpr { struct FnCall { name string + args []Expr } // ------------------------------------------- Statements -type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl +type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param struct VarDecl { name string @@ -162,6 +163,7 @@ struct VarDecl { struct FuncDecl { name string + params []Param ret_type string block Block } @@ -178,6 +180,11 @@ struct Block { stmts []Stmt } +struct Param { + name string + type string +} + // ------------------------------------------- Parser struct Parser { @@ -185,6 +192,7 @@ struct Parser { mut: symbols SymbolTable pos int + line int statements []Stmt } @@ -223,7 +231,7 @@ fn (mut p Parser) dump_stmt() { @[noreturn] fn parse_error(str string) { - eprintln(term.red("Parse Error: " + str)) + eprintln(term.red("Parse Error: ${str}")) panic("") } @@ -259,16 +267,29 @@ fn (mut p Parser) parse_expr(prec Precedence) Expr { } fn (mut p Parser) parse_ident(ident string) Expr { - expr := match p.peek().type { - .increment, .decrement {Expr(UnaryExpr {ident: ident, op: p.next().text})} - .lparen { - p.expect(.lparen) - p.expect(.rparen) - FnCall{name: ident} - } + return match p.peek().type { + .increment, .decrement {UnaryExpr {ident: ident, op: p.next().text}} + .lparen {p.parse_call(ident)} else {Variable{ident, p.symbols.variable_scopes.len}} } - return expr +} + +fn (mut p Parser) parse_call(name string) FnCall { + p.expect(.lparen) + mut args := []Expr{} + + if p.peek().type != .rparen { + for { + args << p.parse_expr(.lowest) + if p.peek().type == .comma { + p.next() + } else { + break + } + } + } + p.expect(.rparen) + return FnCall{name: name, args: args} } fn (mut p Parser) parse_print() PrintExpr { @@ -317,7 +338,7 @@ fn (mut p Parser) check_binary_expr_types(expr BinaryExpr) { left_t := p.get_expr_type(expr.left) right_t := p.get_expr_type(expr.right) if left_t != right_t { - parse_error ('Type mismatch in expression: ${left_t} and ${right_t}') + parse_error('Type mismatch in expression: ${left_t} and ${right_t}') } } @@ -439,6 +460,28 @@ fn (mut p Parser) parse_func_decl() FuncDecl { } p.expect(.lparen) + + mut params := []Param{} + + p.symbols.variable_scopes << map[string]VarSymbolInfo{} + + if p.peek().type != .rparen { + for { + if p.peek().type != .identifier {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} + p_name := p.next().text + if p.peek().type != .type {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} + p_type := p.next().text + params << Param{p_name, p_type} + p.symbols.define_var(p_name, p_type) + + if p.peek().type == .comma { + p.next() + } else { + break + } + } + } + p.expect(.rparen) p.dump_token() @@ -448,7 +491,6 @@ fn (mut p Parser) parse_func_decl() FuncDecl { parse_error("Expected function return type after name when declaring ${name_tok.text}") } - p.symbols.variable_scopes << map[string]VarSymbolInfo{} block := p.parse_block(true) return_stmts := p.get_return_stmts_recursive(block) @@ -468,26 +510,17 @@ fn (mut p Parser) parse_func_decl() FuncDecl { name: name_tok.text ret_type: type_tok.text block: block + params: params } } fn (mut p Parser) parse_return_stmt() ReturnStmt { p.expect(.kw_return) - token := p.peek() - mut expr := Expr{} - expr = match token.type { - .integer {IntegerLiteral{token.text.int()}} - .real {RealLiteral{token.text.f32()}} - .boolean {BoolLiteral{token.text == 'true'}} - .identifier {Variable{token.text, p.symbols.variable_scopes.len}} - .semicolon {VoidExpr{}} - else {parse_error("Unexpected Token")} - } + expr := p.parse_expr(.lowest) + p.next() - if !(expr is VoidExpr) { - p.expect(.semicolon) - } + return ReturnStmt { expr: expr }