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

View File

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

View File

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

View File

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

View File

@ -45,6 +45,7 @@ mut:
mod string
unresolved []ast.Expr
unresolved_offset int
expected_type table.Type
}
// for tests
@ -471,13 +472,13 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
if p.peek_tok.kind == .lpar {
name := p.tok.lit
// 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 {
to_typ := p.parse_type()
p.check(.lpar)
mut expr := ast.Expr{}
expr,_ = p.expr(0)
// TODO, string(b, len)
expr,_ = p.expr(0)
// TODO, string(b, len)
if table.type_idx(to_typ) == table.string_type_idx && p.tok.kind == .comma {
p.check(.comma)
p.expr(0) // len
@ -487,7 +488,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
typ: to_typ
expr: expr
}
return node, to_typ
return node,to_typ
}
// fn call
else {
@ -540,6 +541,10 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.str {
node,typ = p.string_expr()
}
.dot {
// .enum_val
node,typ = p.enum_val()
}
.chartoken {
typ = table.byte_type
node = ast.CharLiteral{
@ -562,7 +567,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
p.next()
}
.key_match {
return p.match_expr()
node,typ = p.match_expr()
}
.number {
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]
}
*/
// `.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 {
p.check(.key_for)
@ -815,7 +829,8 @@ fn (p mut Parser) for_statement() ast.Stmt {
}
p.check(.key_in)
mut elem_type := table.void_type
/*arr_expr*/_,arr_typ := p.expr(0)
// arr_expr
_,arr_typ := p.expr(0)
// array / map
arr_typ_sym := p.table.get_type_symbol(arr_typ)
match arr_typ_sym.info {
@ -826,10 +841,11 @@ fn (p mut Parser) for_statement() ast.Stmt {
elem_type = it.value_type
}
else {
//elem_type_sym := p.table.get_type_symbol(elem_type)
//p.error('cannot loop over type: $elem_type_sym.name')
println(1)
// elem_type_sym := p.table.get_type_symbol(elem_type)
// p.error('cannot loop over type: $elem_type_sym.name')
}
}
}
// 0 .. 10
// start := p.tok.lit.int()
if p.tok.kind == .dotdot {
@ -922,7 +938,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
}
p.check(.str_dollar)
p.expr(0)
if p.tok.kind == .semicolon {
if p.tok.kind == .colon {
p.next()
}
}
@ -945,6 +961,7 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
// []
else {
// TODO ?
println(0)
}
}
else {
@ -966,18 +983,15 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
is_fixed = true
val_type = p.parse_type()
match exprs[0] {
ast.IntegerLiteral { fixed_size = it.val }
ast.IntegerLiteral {
fixed_size = it.val
}
else {}
}
}
p.warn('fixed size array')
}
}
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)
}
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) }
array_type := table.new_type(idx)
node = ast.ArrayInit{
typ: array_type
@ -1252,19 +1266,19 @@ fn (p mut Parser) global_decl() ast.GlobalDecl {
p.table.register_global(name, typ)
// p.genln(p.table.cgen_name_type_pair(name, typ))
/*
mut g := p.table.cgen_name_type_pair(name, typ)
if p.tok == .assign {
p.next()
g += ' = '
_,expr := p.tmp_expr()
g += expr
}
// p.genln('; // global')
g += '; // global'
if !p.cgen.nogen {
p.cgen.consts << g
}
*/
mut g := p.table.cgen_name_type_pair(name, typ)
if p.tok == .assign {
p.next()
g += ' = '
_,expr := p.tmp_expr()
g += expr
}
// p.genln('; // global')
g += '; // global'
if !p.cgen.nogen {
p.cgen.consts << g
}
*/
return ast.GlobalDecl{
name: name
@ -1277,13 +1291,15 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
p.check(.lcbr)
mut blocks := []ast.StmtBlock
mut match_exprs := []ast.Expr
mut return_type := table.void_type
for {
// p.tok.kind != .rcbr {
match_expr,_ := p.expr(0)
match_exprs << match_expr
p.warn('match block')
stmts := p.parse_block()
blocks << ast.StmtBlock{
stmts: p.parse_block()
stmts: stmts
}
if p.tok.kind == .key_else {
p.next()
@ -1291,6 +1307,17 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
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 {
break
}
@ -1303,7 +1330,7 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
typ: typ
cond: cond
}
return node,table.void_type
return node,return_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.tmp_cnt = 0
}
pub fn (t &Table) find_fn(name string) ?Fn {
@ -224,7 +225,6 @@ pub fn (t &TypeSymbol) find_method(name string) ?Fn {
return none
}
pub fn (s &TypeSymbol) has_field(name string) bool {
s.find_field(name) or {
return false
@ -235,7 +235,7 @@ pub fn (s &TypeSymbol) has_field(name string) bool {
pub fn (s &TypeSymbol) find_field(name string) ?Field {
match s.info {
Struct {
for field in it.fields {
for field in it.fields {
if field.name == name {
return field
}
@ -302,7 +302,8 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
kind: .unresolved
name: 'unresolved-$unresolved_idx'
}
} else if idx > 0 {
}
else if idx > 0 {
return &t.types[idx]
}
// 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 {
existing_type := &t.types[existing_idx]
t.types[existing_idx] = { typ | kind: existing_type.kind }
} else {
t.types[existing_idx] = {
typ |
kind:existing_type.kind
}
}
else {
t.types[existing_idx] = typ
}
}
@ -473,8 +478,7 @@ pub fn (t &Table) check(got, expected Type) bool {
if exp_type_sym.kind == .voidptr {
return true
}
if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] &&
exp_type_sym.kind in [.voidptr, .byteptr, .charptr] {
if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && exp_type_sym.kind in [.voidptr, .byteptr, .charptr] {
return true
}
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' {
// 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 true