parser: `[]int{cap:cap, len:len}` syntax; minor fixes

pull/4404/head^2
Alexander Medvednikov 2020-04-14 18:09:59 +02:00
parent 893d14ef8f
commit ec10831318
7 changed files with 79 additions and 26 deletions

View File

@ -691,3 +691,8 @@ fn test_hex(){
st1 := [byte(0x41)].repeat(100) st1 := [byte(0x41)].repeat(100)
assert st1.hex() == "41".repeat(100) assert st1.hex() == "41".repeat(100)
} }
fn test_array_with_cap() {
a := []int{cap:10, len:1 }
//assert a.len == 1
}

View File

@ -444,6 +444,9 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
if typ_sym.kind == .void && arg_typ_sym.kind == .string { if typ_sym.kind == .void && arg_typ_sym.kind == .string {
continue continue
} }
if f.is_generic {
continue
}
if typ_sym.kind == .array_fixed { if typ_sym.kind == .array_fixed {
} }
// println('fixed') // println('fixed')
@ -1333,7 +1336,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
c.error('match 0 cond type', node.pos) c.error('match 0 cond type', node.pos)
} }
type_sym := c.table.get_type_symbol(cond_type) type_sym := c.table.get_type_symbol(cond_type)
// all_possible_left_subtypes is a histogram of // all_possible_left_subtypes is a histogram of
// type => how many times it was used in the match // type => how many times it was used in the match
mut all_possible_left_subtypes := map[string]int mut all_possible_left_subtypes := map[string]int
@ -1343,7 +1345,7 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
match type_sym.info { match type_sym.info {
table.SumType { table.SumType {
for v in it.variants { for v in it.variants {
all_possible_left_subtypes[ int(v).str() ] = 0 all_possible_left_subtypes[int(v).str()] = 0
} }
} }
table.Enum { table.Enum {
@ -1362,12 +1364,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
ast.Type { ast.Type {
tidx := table.type_idx(it.typ) tidx := table.type_idx(it.typ)
stidx := tidx.str() stidx := tidx.str()
all_possible_left_subtypes[ stidx ] = all_possible_left_subtypes[ stidx ] + 1 all_possible_left_subtypes[stidx] = all_possible_left_subtypes[stidx] +
1
} }
ast.EnumVal { ast.EnumVal {
all_possible_left_enum_vals[ it.val ] = all_possible_left_enum_vals[ it.val ] + 1 all_possible_left_enum_vals[it.val] = all_possible_left_enum_vals[it.val] +
1
} }
else{} else {}
} }
} }
} }
@ -1376,20 +1380,22 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
unhandled := []string unhandled := []string
match type_sym.info { match type_sym.info {
table.SumType { table.SumType {
for k,v in all_possible_left_subtypes { for k, v in all_possible_left_subtypes {
if v == 0 { if v == 0 {
err = true err = true
unhandled << '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' unhandled << '`' + c.table.type_to_str(table.new_type(k.int())) + '`'
} }
if v > 1 { if v > 1 {
err = true err = true
multiple_type_name := '`' + c.table.type_to_str( table.new_type( k.int() ) ) + '`' multiple_type_name := '`' + c.table.type_to_str(table.new_type(k.int())) +
c.error('a match case for $multiple_type_name is handled more than once', node.pos) '`'
c.error('a match case for $multiple_type_name is handled more than once',
node.pos)
} }
} }
} }
table.Enum { table.Enum {
for k,v in all_possible_left_enum_vals { for k, v in all_possible_left_enum_vals {
if v == 0 { if v == 0 {
err = true err = true
unhandled << '`.$k`' unhandled << '`.$k`'
@ -1397,11 +1403,14 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
if v > 1 { if v > 1 {
err = true err = true
multiple_enum_val := '`.$k`' multiple_enum_val := '`.$k`'
c.error('a match case for $multiple_enum_val is handled more than once', node.pos) c.error('a match case for $multiple_enum_val is handled more than once',
node.pos)
} }
} }
} }
else { err = true } else {
err = true
}
} }
if err { if err {
if unhandled.len > 0 { if unhandled.len > 0 {
@ -1410,7 +1419,6 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
c.error(err_details, node.pos) c.error(err_details, node.pos)
} }
} }
c.expected_type = cond_type c.expected_type = cond_type
mut ret_type := table.void_type mut ret_type := table.void_type
for branch in node.branches { for branch in node.branches {

View File

@ -553,6 +553,15 @@ fn (f mut Fmt) expr(node ast.Expr) {
f.write(it.val) f.write(it.val)
} }
ast.MapInit { ast.MapInit {
if it.keys.len == 0 {
if it.value_type == 0 {
f.write('map[string]int') // TODO
return
}
f.write('map[string]')
f.write(f.type_to_str(it.value_type))
return
}
f.writeln('{') f.writeln('{')
f.indent++ f.indent++
for i, key in it.keys { for i, key in it.keys {

View File

@ -212,9 +212,13 @@ pub fn (g mut Gen) typ(t table.Type) string {
if table.type_is(t, .optional) { if table.type_is(t, .optional) {
// Register an optional // Register an optional
styp = 'Option_' + styp styp = 'Option_' + styp
if table.type_is_ptr(t) {
styp = styp.replace('*', '_ptr')
}
if !(styp in g.optionals) { if !(styp in g.optionals) {
// println(styp) // println(styp)
g.typedefs2.writeln('typedef Option $styp;') x := styp // .replace('*', '_ptr') // handle option ptrs
g.typedefs2.writeln('typedef Option $x;')
g.optionals << styp g.optionals << styp
} }
} }
@ -1744,7 +1748,11 @@ fn (g mut Gen) return_statement(node ast.Return) {
mut styp := g.typ(g.fn_decl.return_type) mut styp := g.typ(g.fn_decl.return_type)
if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] != if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
styp = styp[7..] // remove 'Option_' styp = styp[7..] // remove 'Option_'
g.write('opt_ok(& ($styp []) { ') mut x := styp
if x.ends_with('_ptr') {
x = x.replace('_ptr', '*')
}
g.write('opt_ok(&($x/*X*/[]) { ')
} }
g.write('($styp){') g.write('($styp){')
for i, expr in node.exprs { for i, expr in node.exprs {
@ -1783,9 +1791,13 @@ fn (g mut Gen) return_statement(node ast.Return) {
} }
if !is_none && !is_error { if !is_none && !is_error {
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_'
g.write('/*:)$return_sym.name*/opt_ok(&($styp []) { ') mut x := styp
if x.ends_with('_ptr') {
x = x.replace('_ptr', '*')
}
g.write('/*:)$return_sym.name*/opt_ok(&($x[]) { ')
g.expr(node.exprs[0]) g.expr(node.exprs[0])
g.writeln(' }, sizeof($styp));') g.writeln(' }, sizeof($x));')
return return
} }
// g.write('/*OPTIONAL*/') // g.write('/*OPTIONAL*/')

View File

@ -141,7 +141,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.next() p.next()
} }
// <T> // <T>
if p.tok.kind == .lt { is_generic := p.tok.kind == .lt
if is_generic {
p.next() p.next()
p.next() p.next()
p.check(.gt) p.check(.gt)
@ -169,6 +170,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
args: args args: args
return_type: return_type return_type: return_type
is_variadic: is_variadic is_variadic: is_variadic
is_generic: is_generic
}) })
} else { } else {
if is_c { if is_c {
@ -185,6 +187,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
return_type: return_type return_type: return_type
is_variadic: is_variadic is_variadic: is_variadic
is_c: is_c is_c: is_c
is_generic: is_generic
}) })
} }
// Body // Body

View File

@ -1351,15 +1351,12 @@ fn (p mut Parser) array_init() ast.ArrayInit {
// p.check_comment() // p.check_comment()
} }
line_nr := p.tok.line_nr line_nr := p.tok.line_nr
$if tinyc { $if tinyc {
// NB: do not remove the next line without testing // NB: do not remove the next line without testing
// v selfcompilation with tcc first // v selfcompilation with tcc first
tcc_stack_bug := 12345 tcc_stack_bug := 12345
} }
last_pos = p.tok.position() last_pos = p.tok.position()
p.check(.rsbr) p.check(.rsbr)
// [100]byte // [100]byte
if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr {
@ -1376,6 +1373,22 @@ fn (p mut Parser) array_init() ast.ArrayInit {
last_pos = p.tok.position() last_pos = p.tok.position()
p.next() p.next()
} }
if p.tok.kind == .lcbr && exprs.len == 0 {
// `[]int{ len: 10, cap: 100}` syntax
p.next()
for p.tok.kind != .rcbr {
key := p.check_name()
p.check(.colon)
if !(key in ['len', 'cap', 'init']) {
p.error('wrong field `$key`, expecting `len`, `cap`, or `init`')
}
p.expr(0)
if p.tok.kind != .rcbr {
p.check(.comma)
}
}
p.check(.rcbr)
}
pos := token.Position{ pos := token.Position{
line_nr: first_pos.line_nr line_nr: first_pos.line_nr
pos: first_pos.pos pos: first_pos.pos
@ -1594,7 +1607,9 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
// p.expr(0) // p.expr(0)
default_expr = p.expr(0) default_expr = p.expr(0)
match default_expr { match default_expr {
ast.EnumVal { it.typ = typ } ast.EnumVal {
it.typ = typ
}
// TODO: implement all types?? // TODO: implement all types??
else {} else {}
} }
@ -1865,8 +1880,8 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
is_else = true is_else = true
p.next() p.next()
} else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || } else if p.tok.kind == .name && (p.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() &&
(p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) {
// Sum type match // Sum type match
// if sym.kind == .sum_type { // if sym.kind == .sum_type {
// p.warn('is sum') // p.warn('is sum')
@ -1993,7 +2008,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
name := p.check_name() name := p.check_name()
mut sum_variants := []table.Type mut sum_variants := []table.Type
if p.tok.kind == .assign { if p.tok.kind == .assign {
p.next() // TODO require `=` p.next() // TODO require `=`
} }
if p.tok.kind == .key_fn { if p.tok.kind == .key_fn {
// function type: `type mycallback fn(string, int)` // function type: `type mycallback fn(string, int)`
@ -2005,7 +2020,7 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
typ: fn_type typ: fn_type
} }
} }
first_type := p.parse_type() // need to parse the first type before we can check if it's `type A = X | Y` first_type := p.parse_type() // need to parse the first type before we can check if it's `type A = X | Y`
if p.tok.kind == .pipe { if p.tok.kind == .pipe {
p.check(.pipe) p.check(.pipe)
sum_variants << first_type sum_variants << first_type

View File

@ -25,6 +25,7 @@ pub:
return_type Type return_type Type
is_variadic bool is_variadic bool
is_c bool is_c bool
is_generic bool
} }
pub struct Arg { pub struct Arg {