memory fixes: 21% of V compiler leaks fixed
parent
9b9c1cc834
commit
956bf23390
|
@ -73,7 +73,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
for file in files {
|
for file in files {
|
||||||
g.file = file
|
g.file = file
|
||||||
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
||||||
building_v := g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v')
|
building_v := true && (g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v'))
|
||||||
is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v')
|
is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v')
|
||||||
if g.file.path.ends_with('_test.v') {
|
if g.file.path.ends_with('_test.v') {
|
||||||
g.is_test = is_test
|
g.is_test = is_test
|
||||||
|
@ -454,7 +454,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.write('; $i < ')
|
g.write('; $i < ')
|
||||||
g.expr(it.high)
|
g.expr(it.high)
|
||||||
g.writeln('; $i++) { ')
|
g.writeln('; $i++) { ')
|
||||||
g.writeln('int $it.val_var = $i;')
|
g.writeln('\tint $it.val_var = $i;')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
|
@ -467,7 +467,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.write('for (int $i = 0; $i < ')
|
g.write('for (int $i = 0; $i < ')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln('.len; $i++) {')
|
g.writeln('.len; $i++) {')
|
||||||
g.write('$styp $it.val_var = (($styp*)')
|
g.write('\t$styp $it.val_var = (($styp*)')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln('.data)[$i];')
|
g.writeln('.data)[$i];')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
@ -486,8 +486,8 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {')
|
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {')
|
||||||
g.writeln('$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];')
|
g.writeln('\t$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];')
|
||||||
g.write('$val_styp $it.val_var = (*($val_styp*)map_get3(')
|
g.write('\t$val_styp $it.val_var = (*($val_styp*)map_get3(')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln(', $key, &($val_styp[]){ $zero }));')
|
g.writeln(', $key, &($val_styp[]){ $zero }));')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
@ -641,36 +641,28 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mut is_fixed_array_init := false
|
|
||||||
mut is_ident := false
|
|
||||||
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
|
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
|
||||||
|
mut is_fixed_array_init := false
|
||||||
match val {
|
match val {
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
is_fixed_array_init = right_sym.kind == .array_fixed
|
is_fixed_array_init = right_sym.kind == .array_fixed
|
||||||
}
|
}
|
||||||
ast.Ident {
|
|
||||||
is_ident = true
|
|
||||||
}
|
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
is_decl := assign_stmt.op == .decl_assign
|
is_decl := assign_stmt.op == .decl_assign
|
||||||
|
g.write('/*assign_stmt*/')
|
||||||
if is_decl {
|
if is_decl {
|
||||||
g.write('$styp ')
|
g.write('$styp ')
|
||||||
}
|
}
|
||||||
g.expr(ident)
|
g.expr(ident)
|
||||||
if g.autofree && right_sym.kind == .array && is_ident {
|
if g.autofree && right_sym.kind in [.array, .string] {
|
||||||
// `arr1 = arr2` => `arr1 = arr2.clone()`
|
if g.gen_clone_assignment(val, right_sym, true) {
|
||||||
g.write(' = array_clone(&')
|
g.writeln(';')
|
||||||
g.expr(val)
|
// g.expr_var_name = ''
|
||||||
g.write(')')
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if g.autofree && right_sym.kind == .string && is_ident {
|
if !is_fixed_array_init {
|
||||||
// `str1 = str2` => `str1 = str2.clone()`
|
|
||||||
g.write(' = string_clone(')
|
|
||||||
g.expr(val)
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
else if !is_fixed_array_init {
|
|
||||||
g.write(' = ')
|
g.write(' = ')
|
||||||
if !is_decl {
|
if !is_decl {
|
||||||
g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ)
|
g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ)
|
||||||
|
@ -692,6 +684,40 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool {
|
||||||
|
mut is_ident := false
|
||||||
|
match val {
|
||||||
|
ast.Ident {
|
||||||
|
is_ident = true
|
||||||
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
is_ident = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.autofree && right_sym.kind == .array && is_ident {
|
||||||
|
// `arr1 = arr2` => `arr1 = arr2.clone()`
|
||||||
|
if add_eq {
|
||||||
|
g.write('=')
|
||||||
|
}
|
||||||
|
g.write(' array_clone(&')
|
||||||
|
g.expr(val)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
else if g.autofree && right_sym.kind == .string && is_ident {
|
||||||
|
if add_eq {
|
||||||
|
g.write('=')
|
||||||
|
}
|
||||||
|
// `str1 = str2` => `str1 = str2.clone()`
|
||||||
|
g.write(' string_clone(')
|
||||||
|
g.expr(val)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if it.is_c {
|
if it.is_c {
|
||||||
// || it.no_body {
|
// || it.no_body {
|
||||||
|
@ -1173,7 +1199,18 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
g.is_assign_lhs = false
|
g.is_assign_lhs = false
|
||||||
g.expr_with_cast(node.val, node.right_type, node.left_type)
|
right_sym := g.table.get_type_symbol(node.right_type)
|
||||||
|
// left_sym := g.table.get_type_symbol(node.left_type)
|
||||||
|
mut cloned := false
|
||||||
|
// !g.is_array_set
|
||||||
|
if g.autofree && right_sym.kind in [.array, .string] {
|
||||||
|
if g.gen_clone_assignment(node.val, right_sym, false) {
|
||||||
|
cloned = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !cloned {
|
||||||
|
g.expr_with_cast(node.val, node.right_type, node.left_type)
|
||||||
|
}
|
||||||
if g.is_array_set {
|
if g.is_array_set {
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
g.is_array_set = false
|
g.is_array_set = false
|
||||||
|
@ -1397,7 +1434,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) {
|
||||||
ast.Type {
|
ast.Type {
|
||||||
it_type := g.typ(it.typ)
|
it_type := g.typ(it.typ)
|
||||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||||
g.write('$it_type* it = ($it_type*)')
|
g.write('\t$it_type* it = ($it_type*)')
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.writeln('.obj; // ST it')
|
g.writeln('.obj; // ST it')
|
||||||
}
|
}
|
||||||
|
@ -2194,53 +2231,64 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
g.write('$styp $tmp_opt = ')
|
g.write('$styp $tmp_opt = ')
|
||||||
}
|
}
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
g.method_call(node)
|
||||||
if node.left_type == 0 {
|
}
|
||||||
verror('method receiver type is 0, this means there are some uchecked exprs')
|
else {
|
||||||
|
g.fn_call(node)
|
||||||
|
}
|
||||||
|
if gen_or {
|
||||||
|
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) method_call(node ast.CallExpr) {
|
||||||
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
|
if node.left_type == 0 {
|
||||||
|
verror('method receiver type is 0, this means there are some uchecked exprs')
|
||||||
|
}
|
||||||
|
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
mut receiver_name := typ_sym.name
|
||||||
|
if typ_sym.kind == .array && node.name == 'filter' {
|
||||||
|
g.gen_filter(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if typ_sym.kind == .array && node.name in
|
||||||
|
// TODO performance, detect `array` method differently
|
||||||
|
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim',
|
||||||
|
//
|
||||||
|
'first', 'last', 'clone', 'reverse', 'slice'] {
|
||||||
|
// && rec_sym.name == 'array' {
|
||||||
|
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||||
|
// `array_byte_clone` => `array_clone`
|
||||||
|
receiver_name = 'array'
|
||||||
|
if node.name in ['last', 'first'] {
|
||||||
|
return_type_str := g.typ(node.return_type)
|
||||||
|
g.write('*($return_type_str*)')
|
||||||
}
|
}
|
||||||
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
}
|
||||||
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
name := '${receiver_name}_$node.name'.replace('.', '__')
|
||||||
mut receiver_name := typ_sym.name
|
// if node.receiver_type != 0 {
|
||||||
if typ_sym.kind == .array && node.name == 'filter' {
|
// g.write('/*${g.typ(node.receiver_type)}*/')
|
||||||
g.gen_filter(node)
|
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
|
||||||
return
|
// }
|
||||||
}
|
g.write('${name}(')
|
||||||
if typ_sym.kind == .array && node.name in
|
if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) {
|
||||||
// TODO performance, detect `array` method differently
|
// The receiver is a reference, but the caller provided a value
|
||||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim',
|
// Add `&` automatically.
|
||||||
//
|
// TODO same logic in call_args()
|
||||||
'first', 'last', 'clone', 'reverse', 'slice'] {
|
g.write('&')
|
||||||
// && rec_sym.name == 'array' {
|
}
|
||||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) {
|
||||||
// `array_byte_clone` => `array_clone`
|
g.write('/*rec*/*')
|
||||||
receiver_name = 'array'
|
}
|
||||||
if node.name in ['last', 'first'] {
|
g.expr(node.left)
|
||||||
return_type_str := g.typ(node.return_type)
|
is_variadic := node.exp_arg_types.len > 0 && table.type_is_variadic(node.exp_arg_types[node.exp_arg_types.len - 1])
|
||||||
g.write('*($return_type_str*)')
|
if node.args.len > 0 || is_variadic {
|
||||||
}
|
g.write(', ')
|
||||||
}
|
}
|
||||||
name := '${receiver_name}_$node.name'.replace('.', '__')
|
// /////////
|
||||||
// if node.receiver_type != 0 {
|
/*
|
||||||
// g.write('/*${g.typ(node.receiver_type)}*/')
|
|
||||||
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
|
|
||||||
// }
|
|
||||||
g.write('${name}(')
|
|
||||||
if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) {
|
|
||||||
// The receiver is a reference, but the caller provided a value
|
|
||||||
// Add `&` automatically.
|
|
||||||
// TODO same logic in call_args()
|
|
||||||
g.write('&')
|
|
||||||
}
|
|
||||||
else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) {
|
|
||||||
g.write('/*rec*/*')
|
|
||||||
}
|
|
||||||
g.expr(node.left)
|
|
||||||
is_variadic := node.exp_arg_types.len > 0 && table.type_is_variadic(node.exp_arg_types[node.exp_arg_types.len - 1])
|
|
||||||
if node.args.len > 0 || is_variadic {
|
|
||||||
g.write(', ')
|
|
||||||
}
|
|
||||||
// /////////
|
|
||||||
/*
|
|
||||||
if name.contains('subkeys') {
|
if name.contains('subkeys') {
|
||||||
println('call_args $name $node.arg_types.len')
|
println('call_args $name $node.arg_types.len')
|
||||||
for t in node.arg_types {
|
for t in node.arg_types {
|
||||||
|
@ -2250,23 +2298,27 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// ///////
|
// ///////
|
||||||
g.call_args(node.args, node.exp_arg_types)
|
g.call_args(node.args, node.exp_arg_types)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
|
mut name := node.name
|
||||||
|
is_print := name == 'println'
|
||||||
|
if node.is_c {
|
||||||
|
// Skip "C."
|
||||||
|
g.is_c_call = true
|
||||||
|
name = name[2..].replace('.', '__')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mut name := node.name
|
name = c_name(name)
|
||||||
is_print := name == 'println'
|
}
|
||||||
if node.is_c {
|
// Generate tmp vars for values that have to be freed.
|
||||||
// Skip "C."
|
/*
|
||||||
g.is_c_call = true
|
|
||||||
name = name[2..].replace('.', '__')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
name = c_name(name)
|
|
||||||
}
|
|
||||||
// Generate tmp vars for values that have to be freed.
|
|
||||||
/*
|
|
||||||
mut tmps := []string
|
mut tmps := []string
|
||||||
for arg in node.args {
|
for arg in node.args {
|
||||||
if arg.typ == table.string_type_idx || is_print {
|
if arg.typ == table.string_type_idx || is_print {
|
||||||
|
@ -2279,43 +2331,42 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if is_print && node.args[0].typ != table.string_type_idx {
|
if is_print && node.args[0].typ != table.string_type_idx {
|
||||||
typ := node.args[0].typ
|
typ := node.args[0].typ
|
||||||
mut styp := g.typ(typ)
|
mut styp := g.typ(typ)
|
||||||
sym := g.table.get_type_symbol(typ)
|
sym := g.table.get_type_symbol(typ)
|
||||||
if !sym.has_method('str') && !(int(typ) in g.str_types) {
|
if !sym.has_method('str') && !(int(typ) in g.str_types) {
|
||||||
// Generate an automatic str() method if this type doesn't have it already
|
// Generate an automatic str() method if this type doesn't have it already
|
||||||
if table.type_is_ptr(typ) {
|
if table.type_is_ptr(typ) {
|
||||||
styp = styp.replace('*', '')
|
styp = styp.replace('*', '')
|
||||||
}
|
|
||||||
g.str_types << typ
|
|
||||||
g.definitions.writeln('string ${styp}_str($styp* x) { return tos3("TODO_str"); }')
|
|
||||||
}
|
|
||||||
if g.autofree && !table.type_is_optional(typ) {
|
|
||||||
tmp := g.new_tmp_var()
|
|
||||||
// tmps << tmp
|
|
||||||
g.write('string $tmp = ${styp}_str(')
|
|
||||||
g.expr(node.args[0].expr)
|
|
||||||
g.writeln('); println($tmp); string_free($tmp); //MEM2 $styp')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// `println(int_str(10))`
|
|
||||||
// sym := g.table.get_type_symbol(node.args[0].typ)
|
|
||||||
g.write('println(${styp}_str(')
|
|
||||||
g.expr(node.args[0].expr)
|
|
||||||
g.write('))')
|
|
||||||
}
|
}
|
||||||
|
g.str_types << typ
|
||||||
|
g.definitions.writeln('string ${styp}_str($styp* x) { return tos3("TODO_str"); }')
|
||||||
|
}
|
||||||
|
if g.autofree && !table.type_is_optional(typ) {
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
// tmps << tmp
|
||||||
|
g.write('string $tmp = ${styp}_str(')
|
||||||
|
g.expr(node.args[0].expr)
|
||||||
|
g.writeln('); println($tmp); string_free($tmp); //MEM2 $styp')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('${name}(')
|
// `println(int_str(10))`
|
||||||
g.call_args(node.args, node.exp_arg_types)
|
// sym := g.table.get_type_symbol(node.args[0].typ)
|
||||||
g.write(')')
|
g.write('println(${styp}_str(')
|
||||||
|
g.expr(node.args[0].expr)
|
||||||
|
g.write('))')
|
||||||
}
|
}
|
||||||
g.is_c_call = false
|
|
||||||
}
|
}
|
||||||
if gen_or {
|
else {
|
||||||
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
g.write('${name}(')
|
||||||
|
g.call_args(node.args, node.exp_arg_types)
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
|
g.is_c_call = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If user is accessing the return value eg. in assigment, pass the variable name.
|
// If user is accessing the return value eg. in assigment, pass the variable name.
|
||||||
|
|
|
@ -26,10 +26,10 @@ fn (p mut Parser) comp_if() ast.CompIf {
|
||||||
// `$if os {` for a different target, skip everything inside
|
// `$if os {` for a different target, skip everything inside
|
||||||
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
||||||
// on non-Windows systems)
|
// on non-Windows systems)
|
||||||
if ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
|
if false && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
|
||||||
skip_os = true
|
skip_os = true
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
//p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
// p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
||||||
mut stack := 1
|
mut stack := 1
|
||||||
for {
|
for {
|
||||||
if p.tok.kind == .key_return {
|
if p.tok.kind == .key_return {
|
||||||
|
@ -75,7 +75,7 @@ fn (p mut Parser) comp_if() ast.CompIf {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
todo_delete_me = pref.OS.linux // TODO import warning bug
|
todo_delete_me = pref.OS.linux // TODO import warning bug
|
||||||
)
|
)
|
||||||
|
|
||||||
fn os_from_string(os string) pref.OS {
|
fn os_from_string(os string) pref.OS {
|
||||||
|
|
|
@ -70,9 +70,10 @@ pub fn (p mut Parser) parse_multi_return_type() table.Type {
|
||||||
pub fn (p mut Parser) parse_fn_type(name string) table.Type {
|
pub fn (p mut Parser) parse_fn_type(name string) table.Type {
|
||||||
// p.warn('parse fn')
|
// p.warn('parse fn')
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
args, is_variadic := p.fn_args()
|
line_nr := p.tok.line_nr
|
||||||
|
args,is_variadic := p.fn_args()
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
if p.tok.kind.is_start_of_type() {
|
if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() {
|
||||||
return_type = p.parse_type()
|
return_type = p.parse_type()
|
||||||
}
|
}
|
||||||
func := table.Fn{
|
func := table.Fn{
|
||||||
|
@ -96,7 +97,7 @@ pub fn (p mut Parser) parse_type() table.Type {
|
||||||
mut nr_muls := 0
|
mut nr_muls := 0
|
||||||
for p.tok.kind in [.and, .amp] {
|
for p.tok.kind in [.and, .amp] {
|
||||||
if p.tok.kind == .and {
|
if p.tok.kind == .and {
|
||||||
nr_muls+=2
|
nr_muls += 2
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nr_muls++
|
nr_muls++
|
||||||
|
|
|
@ -1520,6 +1520,13 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
// p.warn('field $field_name')
|
// p.warn('field $field_name')
|
||||||
typ := p.parse_type()
|
typ := p.parse_type()
|
||||||
|
/*
|
||||||
|
if name == '_net_module_s' {
|
||||||
|
s := p.table.get_type_symbol(typ)
|
||||||
|
println('XXXX' + s.str())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Default value
|
// Default value
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
p.next()
|
p.next()
|
||||||
|
|
Loading…
Reference in New Issue