v2: match expr; enum val; string formatting

pull/3715/head
Alexander Medvednikov 2020-02-10 20:33:34 +01:00
parent d51c159160
commit 26cfaa150e
6 changed files with 106 additions and 52 deletions

View File

@ -8,12 +8,13 @@ import (
v.table v.table
) )
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | CastExpr AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
CastExpr | EnumVal
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
HashStmt | AssignStmt HashStmt | AssignStmt
// | IncDecStmt k // | IncDecStmt k
// Stand-alone expression in a statement list. // Stand-alone expression in a statement list.
@ -366,6 +367,12 @@ pub:
name string name string
} }
pub struct EnumVal{
pub:
name string
}
pub struct AssignExpr { pub struct AssignExpr {
pub: pub:
op token.Kind op token.Kind

View File

@ -92,6 +92,13 @@ multi_return_int_string multi_return() {
void variadic(variadic_int a) { void variadic(variadic_int a) {
int x = path_sep; int x = path_sep;
int y = if (true) {
1;
}
else {
0;
}
;
} }
void ensure_cap(int required, int cap) { void ensure_cap(int required, int cap) {
@ -105,12 +112,12 @@ void println(string s) {
void matches() { void matches() {
int a = 100; int a = 100;
int tmp1 = a; int tmp2 = a;
if tmp1 == 10{ if tmp2 == 10{
println(tos3("10")); println(tos3("10"));
} }
if tmp1 == 20{ if tmp2 == 20{
int k = a + 1; int k = a + 1;
} }

View File

@ -98,6 +98,7 @@ fn multi_return() (int,string) {
fn variadic(a ...int) { fn variadic(a ...int) {
x := path_sep x := path_sep
y := if true { 1 } else { 0 } // TODO cgen
} }
fn ensure_cap(required int, cap int) { fn ensure_cap(required int, cap int) {
@ -118,6 +119,13 @@ fn matches() {
k := a + 1 k := a + 1
} }
} }
/*
n := match a {
1 { 10 }
2 { 20 }
else { 30 }
}
*/
} }
const ( const (

View File

@ -18,6 +18,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
name: fn_name name: fn_name
args: args args: args
// tok: tok // tok: tok
pos: tok.position() pos: tok.position()
} }
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
@ -121,7 +122,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
typ: arg_type typ: arg_type
} }
args << arg args << arg
//p.table.register_var(arg) // p.table.register_var(arg)
ast_args << ast.Arg{ ast_args << ast.Arg{
name: arg_name name: arg_name
typ: arg_type typ: arg_type
@ -156,7 +157,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
name: arg_name name: arg_name
typ: typ typ: typ
} }
//if typ.typ.kind == .variadic && p.tok.kind == .comma { // if typ.typ.kind == .variadic && p.tok.kind == .comma {
if is_variadic && p.tok.kind == .comma { if is_variadic && p.tok.kind == .comma {
p.error('cannot use ...(variadic) with non-final parameter $arg_name') p.error('cannot use ...(variadic) with non-final parameter $arg_name')
} }

View File

@ -45,6 +45,7 @@ mut:
mod string mod string
unresolved []ast.Expr unresolved []ast.Expr
unresolved_offset int unresolved_offset int
expected_type table.Type
} }
// for tests // for tests
@ -471,13 +472,13 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
if p.peek_tok.kind == .lpar { if p.peek_tok.kind == .lpar {
name := p.tok.lit name := p.tok.lit
// type cast. TODO: finish // type cast. TODO: finish
//if name in table.builtin_type_names { // if name in table.builtin_type_names {
if name in p.table.type_idxs { if name in p.table.type_idxs {
to_typ := p.parse_type() to_typ := p.parse_type()
p.check(.lpar) p.check(.lpar)
mut expr := ast.Expr{} mut expr := ast.Expr{}
expr,_ = p.expr(0) expr,_ = p.expr(0)
// TODO, string(b, len) // TODO, string(b, len)
if table.type_idx(to_typ) == table.string_type_idx && p.tok.kind == .comma { if table.type_idx(to_typ) == table.string_type_idx && p.tok.kind == .comma {
p.check(.comma) p.check(.comma)
p.expr(0) // len p.expr(0) // len
@ -487,7 +488,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
typ: to_typ typ: to_typ
expr: expr expr: expr
} }
return node, to_typ return node,to_typ
} }
// fn call // fn call
else { else {
@ -540,6 +541,10 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.str { .str {
node,typ = p.string_expr() node,typ = p.string_expr()
} }
.dot {
// .enum_val
node,typ = p.enum_val()
}
.chartoken { .chartoken {
typ = table.byte_type typ = table.byte_type
node = ast.CharLiteral{ node = ast.CharLiteral{
@ -562,7 +567,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
p.next() p.next()
} }
.key_match { .key_match {
return p.match_expr() node,typ = p.match_expr()
} }
.number { .number {
node,typ = p.parse_number_literal() node,typ = p.parse_number_literal()
@ -747,7 +752,16 @@ fn (p &Parser) is_addative() bool {
return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name] return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name]
} }
*/ */
// `.green`
fn (p mut Parser) enum_val() (ast.Expr,table.Type) {
p.check(.dot)
name := p.check_name()
mut node := ast.Expr{}
node = ast.EnumVal{
name: name
}
return node,table.bool_type
}
fn (p mut Parser) for_statement() ast.Stmt { fn (p mut Parser) for_statement() ast.Stmt {
p.check(.key_for) p.check(.key_for)
@ -815,7 +829,8 @@ fn (p mut Parser) for_statement() ast.Stmt {
} }
p.check(.key_in) p.check(.key_in)
mut elem_type := table.void_type mut elem_type := table.void_type
/*arr_expr*/_,arr_typ := p.expr(0) // arr_expr
_,arr_typ := p.expr(0)
// array / map // array / map
arr_typ_sym := p.table.get_type_symbol(arr_typ) arr_typ_sym := p.table.get_type_symbol(arr_typ)
match arr_typ_sym.info { match arr_typ_sym.info {
@ -826,10 +841,11 @@ fn (p mut Parser) for_statement() ast.Stmt {
elem_type = it.value_type elem_type = it.value_type
} }
else { else {
//elem_type_sym := p.table.get_type_symbol(elem_type) println(1)
//p.error('cannot loop over type: $elem_type_sym.name') // elem_type_sym := p.table.get_type_symbol(elem_type)
// p.error('cannot loop over type: $elem_type_sym.name')
} }
} }
// 0 .. 10 // 0 .. 10
// start := p.tok.lit.int() // start := p.tok.lit.int()
if p.tok.kind == .dotdot { if p.tok.kind == .dotdot {
@ -922,7 +938,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
} }
p.check(.str_dollar) p.check(.str_dollar)
p.expr(0) p.expr(0)
if p.tok.kind == .semicolon { if p.tok.kind == .colon {
p.next() p.next()
} }
} }
@ -945,6 +961,7 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
// [] // []
else { else {
// TODO ? // TODO ?
println(0)
} }
} }
else { else {
@ -966,18 +983,15 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
is_fixed = true is_fixed = true
val_type = p.parse_type() val_type = p.parse_type()
match exprs[0] { match exprs[0] {
ast.IntegerLiteral { fixed_size = it.val } ast.IntegerLiteral {
fixed_size = it.val
}
else {} else {}
} }
p.warn('fixed size array') p.warn('fixed size array')
} }
} }
idx := if is_fixed { idx := if is_fixed { p.table.find_or_register_array_fixed(val_type, fixed_size, 1) } else { p.table.find_or_register_array(val_type, 1) }
p.table.find_or_register_array_fixed(val_type, fixed_size, 1)
}
else {
p.table.find_or_register_array(val_type, 1)
}
array_type := table.new_type(idx) array_type := table.new_type(idx)
node = ast.ArrayInit{ node = ast.ArrayInit{
typ: array_type typ: array_type
@ -1252,19 +1266,19 @@ fn (p mut Parser) global_decl() ast.GlobalDecl {
p.table.register_global(name, typ) p.table.register_global(name, typ)
// p.genln(p.table.cgen_name_type_pair(name, typ)) // p.genln(p.table.cgen_name_type_pair(name, typ))
/* /*
mut g := p.table.cgen_name_type_pair(name, typ) mut g := p.table.cgen_name_type_pair(name, typ)
if p.tok == .assign { if p.tok == .assign {
p.next() p.next()
g += ' = ' g += ' = '
_,expr := p.tmp_expr() _,expr := p.tmp_expr()
g += expr g += expr
} }
// p.genln('; // global') // p.genln('; // global')
g += '; // global' g += '; // global'
if !p.cgen.nogen { if !p.cgen.nogen {
p.cgen.consts << g p.cgen.consts << g
} }
*/ */
return ast.GlobalDecl{ return ast.GlobalDecl{
name: name name: name
@ -1277,13 +1291,15 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
p.check(.lcbr) p.check(.lcbr)
mut blocks := []ast.StmtBlock mut blocks := []ast.StmtBlock
mut match_exprs := []ast.Expr mut match_exprs := []ast.Expr
mut return_type := table.void_type
for { for {
// p.tok.kind != .rcbr { // p.tok.kind != .rcbr {
match_expr,_ := p.expr(0) match_expr,_ := p.expr(0)
match_exprs << match_expr match_exprs << match_expr
p.warn('match block') p.warn('match block')
stmts := p.parse_block()
blocks << ast.StmtBlock{ blocks << ast.StmtBlock{
stmts: p.parse_block() stmts: stmts
} }
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
p.next() p.next()
@ -1291,6 +1307,17 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
stmts: p.parse_block() stmts: p.parse_block()
} }
} }
// If the last statement is an expression, return its type
if stmts.len > 0 {
match stmts[stmts.len - 1] {
ast.ExprStmt {
type_sym := p.table.get_type_symbol(it.typ)
p.warn('match expr ret $type_sym.name')
return_type = it.typ
}
else {}
}
}
if p.tok.kind == .rcbr { if p.tok.kind == .rcbr {
break break
} }
@ -1303,7 +1330,7 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
typ: typ typ: typ
cond: cond cond: cond
} }
return node,table.void_type return node,return_type
} }
fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.Type { fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.Type {

View File

@ -168,6 +168,7 @@ pub fn (p mut Table) clear_vars() {
// ///} // ///}
p.local_vars = [] p.local_vars = []
} }
p.tmp_cnt = 0
} }
pub fn (t &Table) find_fn(name string) ?Fn { pub fn (t &Table) find_fn(name string) ?Fn {
@ -224,7 +225,6 @@ pub fn (t &TypeSymbol) find_method(name string) ?Fn {
return none return none
} }
pub fn (s &TypeSymbol) has_field(name string) bool { pub fn (s &TypeSymbol) has_field(name string) bool {
s.find_field(name) or { s.find_field(name) or {
return false return false
@ -235,7 +235,7 @@ pub fn (s &TypeSymbol) has_field(name string) bool {
pub fn (s &TypeSymbol) find_field(name string) ?Field { pub fn (s &TypeSymbol) find_field(name string) ?Field {
match s.info { match s.info {
Struct { Struct {
for field in it.fields { for field in it.fields {
if field.name == name { if field.name == name {
return field return field
} }
@ -302,7 +302,8 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
kind: .unresolved kind: .unresolved
name: 'unresolved-$unresolved_idx' name: 'unresolved-$unresolved_idx'
} }
} else if idx > 0 { }
else if idx > 0 {
return &t.types[idx] return &t.types[idx]
} }
// this should never happen // this should never happen
@ -319,8 +320,12 @@ pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int {
if existing_idx >= string_type_idx { if existing_idx >= string_type_idx {
if existing_idx == string_type_idx { if existing_idx == string_type_idx {
existing_type := &t.types[existing_idx] existing_type := &t.types[existing_idx]
t.types[existing_idx] = { typ | kind: existing_type.kind } t.types[existing_idx] = {
} else { typ |
kind:existing_type.kind
}
}
else {
t.types[existing_idx] = typ t.types[existing_idx] = typ
} }
} }
@ -473,8 +478,7 @@ pub fn (t &Table) check(got, expected Type) bool {
if exp_type_sym.kind == .voidptr { if exp_type_sym.kind == .voidptr {
return true return true
} }
if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && exp_type_sym.kind in [.voidptr, .byteptr, .charptr] {
exp_type_sym.kind in [.voidptr, .byteptr, .charptr] {
return true return true
} }
if got_type_sym.is_int() && exp_type_sym.is_int() { if got_type_sym.is_int() && exp_type_sym.is_int() {
@ -489,7 +493,7 @@ pub fn (t &Table) check(got, expected Type) bool {
// if expected.name == 'array' { // if expected.name == 'array' {
// return true // return true
// } // }
if got_idx != exp_idx /*&& got.typ.name != expected.typ.name*/ { if got_idx != exp_idx/*&& got.typ.name != expected.typ.name*/ {
return false return false
} }
return true return true