control flow
This commit is contained in:
23
generator.v
23
generator.v
@@ -112,7 +112,6 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
|
|||||||
g.out.writeln('}')
|
g.out.writeln('}')
|
||||||
}
|
}
|
||||||
FuncDecl {
|
FuncDecl {
|
||||||
dump(stmt.ret_type)
|
|
||||||
c_type := g.mangle_if_class(g.get_c_type(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)}(')
|
g.out.write_string('${c_type} ${mangle_func(stmt.name)}(')
|
||||||
for param in stmt.params {
|
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.out.write_string(') ')
|
||||||
g.gen_stmt(stmt.block)
|
g.gen_stmt(stmt.block)
|
||||||
}
|
}
|
||||||
Param {
|
Param {
|
||||||
@@ -138,6 +137,22 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
|
|||||||
|
|
||||||
g.gen_class_print_func(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 {
|
for i < expr.exprs.len {
|
||||||
inner_expr := expr.exprs[i];
|
inner_expr := expr.exprs[i];
|
||||||
expr_type := expr.types[i];
|
expr_type := expr.types[i];
|
||||||
label := g.get_print_label(inner_expr);
|
|
||||||
if g.symbols.lookup_class(expr_type) != none {
|
if g.symbols.lookup_class(expr_type) != none {
|
||||||
class_name := mangle_struct(expr_type)
|
class_name := mangle_struct(expr_type)
|
||||||
g.out.write_string('print_${class_name}(')
|
g.out.write_string('print_${class_name}(')
|
||||||
@@ -181,7 +195,6 @@ fn (mut g Generator) gen_expr(expr Expr) {
|
|||||||
g.out.write_string(', 0);')
|
g.out.write_string(', 0);')
|
||||||
} else {
|
} else {
|
||||||
g.out.write_string('printf(\"')
|
g.out.write_string('printf(\"')
|
||||||
dump(label);
|
|
||||||
format := get_type_format(expr_type)
|
format := get_type_format(expr_type)
|
||||||
g.out.write_string('%${format}')
|
g.out.write_string('%${format}')
|
||||||
g.out.write_string('\", ')
|
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(\" \");')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.out.write_string('printf(\"\\n\");\n')
|
g.out.write_string('printf(\"\\n\")')
|
||||||
}
|
}
|
||||||
TypeCast {
|
TypeCast {
|
||||||
c_type := g.mangle_if_class(g.get_c_type(expr.type))
|
c_type := g.mangle_if_class(g.get_c_type(expr.type))
|
||||||
|
|||||||
4
lexer.v
4
lexer.v
@@ -8,6 +8,7 @@ enum TokenType as u8 {
|
|||||||
type
|
type
|
||||||
kw_if
|
kw_if
|
||||||
kw_else
|
kw_else
|
||||||
|
kw_elif
|
||||||
kw_for
|
kw_for
|
||||||
kw_break
|
kw_break
|
||||||
kw_fn
|
kw_fn
|
||||||
@@ -99,6 +100,7 @@ fn toktype_from_kw(kw string) TokenType {
|
|||||||
'void', 'real', 'bool', 'int', 'string'{.type}
|
'void', 'real', 'bool', 'int', 'string'{.type}
|
||||||
'if' {.kw_if}
|
'if' {.kw_if}
|
||||||
'else' {.kw_else}
|
'else' {.kw_else}
|
||||||
|
'elif' {.kw_elif}
|
||||||
'for' {.kw_for}
|
'for' {.kw_for}
|
||||||
'break' {.kw_break}
|
'break' {.kw_break}
|
||||||
'fn' {.kw_fn}
|
'fn' {.kw_fn}
|
||||||
@@ -125,7 +127,7 @@ fn is_real(str string) bool {
|
|||||||
|
|
||||||
fn is_keyword(str string) bool {
|
fn is_keyword(str string) bool {
|
||||||
return [
|
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)
|
].contains(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
57
parser.v
57
parser.v
@@ -18,7 +18,7 @@ enum Precedence {
|
|||||||
fn (p Parser) get_precedence(tok_type TokenType) Precedence {
|
fn (p Parser) get_precedence(tok_type TokenType) Precedence {
|
||||||
return match tok_type {
|
return match tok_type {
|
||||||
.equals, .plus_eq, .minus_eq, .star_eq, .slash_eq { .assignment }
|
.equals, .plus_eq, .minus_eq, .star_eq, .slash_eq { .assignment }
|
||||||
.eq_eq, .not_eq, .less_eq, .greater_eq { .comparison }
|
.eq_eq, .not_eq, .less_eq, .greater_eq, .less, .greater { .comparison }
|
||||||
.plus, .minus { .sum }
|
.plus, .minus { .sum }
|
||||||
.star, .slash { .product }
|
.star, .slash { .product }
|
||||||
.dot { .access }
|
.dot { .access }
|
||||||
@@ -194,7 +194,7 @@ struct FnCall {
|
|||||||
|
|
||||||
// ------------------------------------------- Statements
|
// ------------------------------------------- Statements
|
||||||
|
|
||||||
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | ClassDecl
|
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | IfStmt | ElseStmt | ElifStmt | FuncDecl | Param | ClassDecl
|
||||||
|
|
||||||
struct VarDecl {
|
struct VarDecl {
|
||||||
name string
|
name string
|
||||||
@@ -227,6 +227,20 @@ struct Block {
|
|||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IfStmt {
|
||||||
|
condition Expr
|
||||||
|
block Block
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ElseStmt {
|
||||||
|
block Block
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ElifStmt {
|
||||||
|
condition Expr
|
||||||
|
block Block
|
||||||
|
}
|
||||||
|
|
||||||
struct Param {
|
struct Param {
|
||||||
name string
|
name string
|
||||||
type 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 {
|
fn (mut p Parser) parse_binary(left Expr, op string, prec Precedence) BinaryExpr {
|
||||||
//p.next()
|
|
||||||
right := p.parse_expr(prec)
|
right := p.parse_expr(prec)
|
||||||
binary_expr := BinaryExpr{left, op, right}
|
binary_expr := BinaryExpr{left, op, right}
|
||||||
|
|
||||||
|
|
||||||
if !p.is_op_valid_for_type(p.get_expr_type(left), op) {
|
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)}")
|
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 {
|
BinaryExpr {
|
||||||
p.check_binary_expr_types(expr)
|
p.check_binary_expr_types(expr)
|
||||||
left_t := p.get_expr_type(expr.left)
|
left_t := p.get_expr_type(expr.left)
|
||||||
if expr.op in ['<=', '==', '>=', '!='] {
|
if expr.op in ['<=', '==', '>=', '!=', '<', '>'] {
|
||||||
'bool'
|
'bool'
|
||||||
} else {
|
} else {
|
||||||
left_t
|
left_t
|
||||||
@@ -548,6 +560,9 @@ fn (mut p Parser) parse_statement() Stmt {
|
|||||||
.kw_fn {return p.parse_func_decl()}
|
.kw_fn {return p.parse_func_decl()}
|
||||||
.lbracket {return p.parse_block(false)}
|
.lbracket {return p.parse_block(false)}
|
||||||
.kw_class {return p.parse_class()}
|
.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()}
|
else {return p.parse_expr_stmt()}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -693,13 +708,42 @@ fn (mut p Parser) parse_return_stmt() ReturnStmt {
|
|||||||
|
|
||||||
expr := p.parse_expr(.lowest)
|
expr := p.parse_expr(.lowest)
|
||||||
|
|
||||||
p.next()
|
p.expect(.semicolon)
|
||||||
|
|
||||||
return ReturnStmt {
|
return ReturnStmt {
|
||||||
expr: expr
|
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 {
|
fn (mut p Parser) parse_expr_stmt() ExprStmt {
|
||||||
expr := p.parse_expr(.lowest)
|
expr := p.parse_expr(.lowest)
|
||||||
p.expect(.semicolon)
|
p.expect(.semicolon)
|
||||||
@@ -729,7 +773,6 @@ fn (mut p Parser) parse_block(no_scope bool) Block {
|
|||||||
|
|
||||||
p.expect(.rbracket)
|
p.expect(.rbracket)
|
||||||
|
|
||||||
|
|
||||||
return_stmts := (statements.filter(it is ReturnStmt).map(it as ReturnStmt))
|
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]) {
|
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")
|
parse_error("Unexpected use of return. Unreachable code")
|
||||||
|
|||||||
Reference in New Issue
Block a user