Function arguments
This commit is contained in:
30
generator.v
30
generator.v
@@ -8,6 +8,10 @@ mut:
|
|||||||
out strings.Builder
|
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 {
|
fn (mut g Generator) get_c_type(typ string) string {
|
||||||
c_type := if typ == 'real' { 'double' } else { typ }
|
c_type := if typ == 'real' { 'double' } else { typ }
|
||||||
return c_type
|
return c_type
|
||||||
@@ -17,7 +21,7 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
|
|||||||
match stmt {
|
match stmt {
|
||||||
VarDecl {
|
VarDecl {
|
||||||
c_type := g.get_c_type(stmt.type)
|
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.gen_expr(stmt.value)
|
||||||
g.out.writeln(';')
|
g.out.writeln(';')
|
||||||
}
|
}
|
||||||
@@ -39,9 +43,20 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
|
|||||||
}
|
}
|
||||||
FuncDecl {
|
FuncDecl {
|
||||||
c_type := g.get_c_type(stmt.ret_type)
|
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)
|
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())
|
g.out.write_string(expr.val.str())
|
||||||
}
|
}
|
||||||
Variable {
|
Variable {
|
||||||
g.out.write_string('v${expr.name}${expr.scope_depth.str()}')
|
g.out.write_string(mangle_var(expr.name, expr.scope_depth))
|
||||||
}
|
}
|
||||||
UnaryExpr {
|
UnaryExpr {
|
||||||
g.out.write_string('${expr.ident}${expr.op}')
|
g.out.write_string('${expr.ident}${expr.op}')
|
||||||
@@ -91,7 +106,14 @@ fn (mut g Generator) gen_expr(expr Expr) {
|
|||||||
g.out.write_string(')')
|
g.out.write_string(')')
|
||||||
}
|
}
|
||||||
FnCall {
|
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")}
|
else {panic("Unimplemented expression")}
|
||||||
}
|
}
|
||||||
|
|||||||
81
parser.v
81
parser.v
@@ -147,11 +147,12 @@ struct PrintExpr {
|
|||||||
|
|
||||||
struct FnCall {
|
struct FnCall {
|
||||||
name string
|
name string
|
||||||
|
args []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------- Statements
|
// ------------------------------------------- Statements
|
||||||
|
|
||||||
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl
|
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param
|
||||||
|
|
||||||
struct VarDecl {
|
struct VarDecl {
|
||||||
name string
|
name string
|
||||||
@@ -162,6 +163,7 @@ struct VarDecl {
|
|||||||
|
|
||||||
struct FuncDecl {
|
struct FuncDecl {
|
||||||
name string
|
name string
|
||||||
|
params []Param
|
||||||
ret_type string
|
ret_type string
|
||||||
block Block
|
block Block
|
||||||
}
|
}
|
||||||
@@ -178,6 +180,11 @@ struct Block {
|
|||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Param {
|
||||||
|
name string
|
||||||
|
type string
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------- Parser
|
// ------------------------------------------- Parser
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
@@ -185,6 +192,7 @@ struct Parser {
|
|||||||
mut:
|
mut:
|
||||||
symbols SymbolTable
|
symbols SymbolTable
|
||||||
pos int
|
pos int
|
||||||
|
line int
|
||||||
statements []Stmt
|
statements []Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +231,7 @@ fn (mut p Parser) dump_stmt() {
|
|||||||
|
|
||||||
@[noreturn]
|
@[noreturn]
|
||||||
fn parse_error(str string) {
|
fn parse_error(str string) {
|
||||||
eprintln(term.red("Parse Error: " + str))
|
eprintln(term.red("Parse Error: ${str}"))
|
||||||
panic("")
|
panic("")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,16 +267,29 @@ fn (mut p Parser) parse_expr(prec Precedence) Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) parse_ident(ident string) Expr {
|
fn (mut p Parser) parse_ident(ident string) Expr {
|
||||||
expr := match p.peek().type {
|
return match p.peek().type {
|
||||||
.increment, .decrement {Expr(UnaryExpr {ident: ident, op: p.next().text})}
|
.increment, .decrement {UnaryExpr {ident: ident, op: p.next().text}}
|
||||||
.lparen {
|
.lparen {p.parse_call(ident)}
|
||||||
p.expect(.lparen)
|
|
||||||
p.expect(.rparen)
|
|
||||||
FnCall{name: ident}
|
|
||||||
}
|
|
||||||
else {Variable{ident, p.symbols.variable_scopes.len}}
|
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 {
|
fn (mut p Parser) parse_print() PrintExpr {
|
||||||
@@ -439,6 +460,28 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.expect(.lparen)
|
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.expect(.rparen)
|
||||||
|
|
||||||
p.dump_token()
|
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}")
|
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)
|
block := p.parse_block(true)
|
||||||
|
|
||||||
return_stmts := p.get_return_stmts_recursive(block)
|
return_stmts := p.get_return_stmts_recursive(block)
|
||||||
@@ -468,26 +510,17 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
|
|||||||
name: name_tok.text
|
name: name_tok.text
|
||||||
ret_type: type_tok.text
|
ret_type: type_tok.text
|
||||||
block: block
|
block: block
|
||||||
|
params: params
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) parse_return_stmt() ReturnStmt {
|
fn (mut p Parser) parse_return_stmt() ReturnStmt {
|
||||||
p.expect(.kw_return)
|
p.expect(.kw_return)
|
||||||
|
|
||||||
token := p.peek()
|
expr := p.parse_expr(.lowest)
|
||||||
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")}
|
|
||||||
}
|
|
||||||
p.next()
|
p.next()
|
||||||
if !(expr is VoidExpr) {
|
|
||||||
p.expect(.semicolon)
|
|
||||||
}
|
|
||||||
return ReturnStmt {
|
return ReturnStmt {
|
||||||
expr: expr
|
expr: expr
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user