ast: expr.Position; struct field refactoring
parent
8bb11d9035
commit
402e55d115
|
@ -157,15 +157,23 @@ pub:
|
||||||
field_names []string
|
field_names []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct StructInitField {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
expr Expr
|
||||||
|
pos token.Position
|
||||||
|
mut:
|
||||||
|
typ table.Type
|
||||||
|
expected_type table.Type
|
||||||
|
}
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
pub:
|
pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
fields []string
|
fields []StructInitField
|
||||||
exprs []Expr
|
is_short bool
|
||||||
mut:
|
mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
expr_types []table.Type
|
|
||||||
expected_types []table.Type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// import statement
|
// import statement
|
||||||
|
@ -723,3 +731,86 @@ pub fn expr_is_call(expr Expr) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (expr Expr) position() token.Position {
|
||||||
|
// all uncommented have to be implemented
|
||||||
|
match mut expr {
|
||||||
|
ArrayInit {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
AsCast {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.Ident { }
|
||||||
|
AssignExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.CastExpr { }
|
||||||
|
Assoc {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.BoolLiteral { }
|
||||||
|
CallExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.CharLiteral { }
|
||||||
|
EnumVal {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.FloatLiteral { }
|
||||||
|
IfExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.IfGuardExpr { }
|
||||||
|
IndexExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
InfixExpr {
|
||||||
|
left_pos := it.left.position()
|
||||||
|
right_pos := it.right.position()
|
||||||
|
if left_pos.pos == 0 || right_pos.pos == 0 {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
return token.Position{
|
||||||
|
line_nr: it.pos.line_nr
|
||||||
|
pos: left_pos.pos
|
||||||
|
len: right_pos.pos - left_pos.pos + right_pos.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntegerLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
MapInit {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
MatchExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
PostfixExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.None { }
|
||||||
|
PrefixExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.ParExpr { }
|
||||||
|
SelectorExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.SizeOf { }
|
||||||
|
StringLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
StringInterLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.Type { }
|
||||||
|
StructInit {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
// ast.TypeOf { }
|
||||||
|
else {
|
||||||
|
return token.Position{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -123,56 +123,51 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
||||||
// string & array are also structs but .kind of string/array
|
// string & array are also structs but .kind of string/array
|
||||||
.struct_, .string, .array {
|
.struct_, .string, .array {
|
||||||
info := type_sym.info as table.Struct
|
info := type_sym.info as table.Struct
|
||||||
is_short_syntax := struct_init.fields.len == 0
|
if struct_init.is_short && struct_init.fields.len > info.fields.len {
|
||||||
if struct_init.exprs.len > info.fields.len {
|
|
||||||
c.error('too many fields', struct_init.pos)
|
c.error('too many fields', struct_init.pos)
|
||||||
}
|
}
|
||||||
mut inited_fields := []string
|
mut inited_fields := []string
|
||||||
for i, expr in struct_init.exprs {
|
for i, field in struct_init.fields {
|
||||||
if is_short_syntax && i >= info.fields.len {
|
mut info_field := table.Field{}
|
||||||
|
mut field_name := ''
|
||||||
|
if struct_init.is_short {
|
||||||
|
if i >= info.fields.len {
|
||||||
// It doesn't make sense to check for fields that don't exist.
|
// It doesn't make sense to check for fields that don't exist.
|
||||||
// We should just stop here.
|
// We should just stop here.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// struct_field info.
|
info_field = info.fields[i]
|
||||||
field_name := if is_short_syntax { info.fields[i].name } else { struct_init.fields[i] }
|
field_name = info_field.name
|
||||||
if field_name in inited_fields {
|
struct_init.fields[i].name = field_name
|
||||||
c.error('duplicate field name in struct literal: `$field_name`', struct_init.pos)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inited_fields << field_name
|
|
||||||
mut field := if is_short_syntax {
|
|
||||||
info.fields[i]
|
|
||||||
} else {
|
} else {
|
||||||
// There is no guarantee that `i` will not be out of bounds of `info.fields`
|
field_name = field.name
|
||||||
// So we just use an empty field as placeholder here.
|
mut exists := false
|
||||||
table.Field{}
|
|
||||||
}
|
|
||||||
if !is_short_syntax {
|
|
||||||
mut found_field := false
|
|
||||||
for f in info.fields {
|
for f in info.fields {
|
||||||
if f.name == field_name {
|
if f.name == field_name {
|
||||||
field = f
|
info_field = f
|
||||||
found_field = true
|
exists = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found_field {
|
if !exists {
|
||||||
c.error('struct init: no such field `$field_name` for struct `$type_sym.name`',
|
c.error('struct init: no such field `$field.name` for struct `$type_sym.name`', field.pos)
|
||||||
struct_init.pos)
|
continue
|
||||||
|
}
|
||||||
|
if field_name in inited_fields {
|
||||||
|
c.error('duplicate field name in struct literal: `$field_name`', field.pos)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.expected_type = field.typ
|
inited_fields << field_name
|
||||||
expr_type := c.expr(expr)
|
c.expected_type = info_field.typ
|
||||||
|
expr_type := c.expr(field.expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||||
field_type_sym := c.table.get_type_symbol(field.typ)
|
field_type_sym := c.table.get_type_symbol(info_field.typ)
|
||||||
if !c.table.check(expr_type, field.typ) {
|
if !c.table.check(expr_type, info_field.typ) {
|
||||||
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$field.name`',
|
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$info_field.name`', field.pos)
|
||||||
struct_init.pos)
|
|
||||||
}
|
}
|
||||||
struct_init.expr_types << expr_type
|
struct_init.fields[i].typ = expr_type
|
||||||
struct_init.expected_types << field.typ
|
struct_init.fields[i].expected_type = info_field.typ
|
||||||
}
|
}
|
||||||
// Check uninitialized refs
|
// Check uninitialized refs
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
|
@ -206,7 +201,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
if infix_expr.op == .left_shift {
|
if infix_expr.op == .left_shift {
|
||||||
if left.kind != .array && !left.is_int() {
|
if left.kind != .array && !left.is_int() {
|
||||||
// c.error('<< can only be used with numbers and arrays', infix_expr.pos)
|
// c.error('<< can only be used with numbers and arrays', infix_expr.pos)
|
||||||
c.error('cannot shift type $right.name into $left.name', expr_pos(infix_expr.right))
|
c.error('cannot shift type $right.name into $left.name', infix_expr.right.position())
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
if left.kind == .array {
|
if left.kind == .array {
|
||||||
|
@ -220,7 +215,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
// []T << []T
|
// []T << []T
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
c.error('cannot shift type $right.name into $left.name', expr_pos(infix_expr.right))
|
c.error('cannot shift type $right.name into $left.name', infix_expr.right.position())
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +274,7 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||||
left_type_sym := c.table.get_type_symbol(left_type)
|
left_type_sym := c.table.get_type_symbol(left_type)
|
||||||
right_type_sym := c.table.get_type_symbol(right_type)
|
right_type_sym := c.table.get_type_symbol(right_type)
|
||||||
c.error('cannot assign `$right_type_sym.name` to variable `${assign_expr.left.str()}` of type `$left_type_sym.name`',
|
c.error('cannot assign `$right_type_sym.name` to variable `${assign_expr.left.str()}` of type `$left_type_sym.name`',
|
||||||
expr_pos(assign_expr.val))
|
assign_expr.val.position())
|
||||||
}
|
}
|
||||||
c.check_expr_opt_call(assign_expr.val, right_type, true)
|
c.check_expr_opt_call(assign_expr.val, right_type, true)
|
||||||
}
|
}
|
||||||
|
@ -662,7 +657,7 @@ pub fn (c mut Checker) enum_decl(decl ast.EnumDecl) {
|
||||||
ast.IntegerLiteral {}
|
ast.IntegerLiteral {}
|
||||||
ast.PrefixExpr {}
|
ast.PrefixExpr {}
|
||||||
else {
|
else {
|
||||||
mut pos := expr_pos(field.expr)
|
mut pos := field.expr.position()
|
||||||
if pos.pos == 0 {
|
if pos.pos == 0 {
|
||||||
pos = field.pos
|
pos = field.pos
|
||||||
}
|
}
|
||||||
|
@ -999,7 +994,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
value_type := c.table.value_type(typ)
|
value_type := c.table.value_type(typ)
|
||||||
if value_type == table.void_type {
|
if value_type == table.void_type {
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
c.error('for in: cannot index `$typ_sym.name`', expr_pos(it.cond))
|
c.error('for in: cannot index `$typ_sym.name`', it.cond.position())
|
||||||
}
|
}
|
||||||
it.cond_type = typ
|
it.cond_type = typ
|
||||||
it.kind = sym.kind
|
it.kind = sym.kind
|
||||||
|
@ -1011,7 +1006,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.GoStmt {
|
ast.GoStmt {
|
||||||
if !is_call_expr(it.call_expr) {
|
if !is_call_expr(it.call_expr) {
|
||||||
c.error('expression in `go` must be a function call', expr_pos(it.call_expr))1
|
c.error('expression in `go` must be a function call', it.call_expr.position())
|
||||||
}
|
}
|
||||||
c.expr(it.call_expr)
|
c.expr(it.call_expr)
|
||||||
}
|
}
|
||||||
|
@ -1196,89 +1191,6 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_pos(node ast.Expr) token.Position {
|
|
||||||
// all uncommented have to be implemented
|
|
||||||
match mut node {
|
|
||||||
ast.ArrayInit {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.AsCast {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.Ident { }
|
|
||||||
ast.AssignExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.CastExpr { }
|
|
||||||
ast.Assoc {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.BoolLiteral { }
|
|
||||||
ast.CallExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.CharLiteral { }
|
|
||||||
ast.EnumVal {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.FloatLiteral { }
|
|
||||||
ast.IfExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.IfGuardExpr { }
|
|
||||||
ast.IndexExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.InfixExpr {
|
|
||||||
left_pos := expr_pos(it.left)
|
|
||||||
right_pos := expr_pos(it.right)
|
|
||||||
if left_pos.pos == 0 || right_pos.pos == 0 {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
return token.Position{
|
|
||||||
line_nr: it.pos.line_nr
|
|
||||||
pos: left_pos.pos
|
|
||||||
len: right_pos.pos - left_pos.pos + right_pos.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast.IntegerLiteral {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.MapInit {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.MatchExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.PostfixExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.None { }
|
|
||||||
ast.PrefixExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.ParExpr { }
|
|
||||||
ast.SelectorExpr {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.SizeOf { }
|
|
||||||
ast.StringLiteral {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
ast.StringInterLiteral {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.Type { }
|
|
||||||
ast.StructInit {
|
|
||||||
return it.pos
|
|
||||||
}
|
|
||||||
// ast.TypeOf { }
|
|
||||||
else {
|
|
||||||
return token.Position{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
||||||
if ident.name == c.var_decl_name { // c.checked_ident {
|
if ident.name == c.var_decl_name { // c.checked_ident {
|
||||||
c.error('unresolved: `$ident.name`', ident.pos)
|
c.error('unresolved: `$ident.name`', ident.pos)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/inout/short_struct_too_many.v:6:7: error: too many fields
|
||||||
|
4|
|
||||||
|
5| fn main() {
|
||||||
|
6| t := Test{true, false}
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
7| }
|
|
@ -0,0 +1,7 @@
|
||||||
|
struct Test {
|
||||||
|
foo bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
t := Test{true, false}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: struct init: no such field `bar` for struct `Test`
|
||||||
|
6| t := Test{
|
||||||
|
7| foo: true
|
||||||
|
8| bar: false
|
||||||
|
^
|
||||||
|
9| }
|
||||||
|
10| }
|
|
@ -0,0 +1,10 @@
|
||||||
|
struct Test {
|
||||||
|
foo bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
t := Test{
|
||||||
|
foo: true
|
||||||
|
bar: false
|
||||||
|
}
|
||||||
|
}
|
|
@ -695,15 +695,15 @@ fn (f mut Fmt) expr(node ast.Expr) {
|
||||||
if name == 'void' {
|
if name == 'void' {
|
||||||
name = ''
|
name = ''
|
||||||
}
|
}
|
||||||
if it.fields.len == 0 && it.exprs.len == 0 {
|
if it.fields.len == 0 {
|
||||||
// `Foo{}` on one line if there are no fields
|
// `Foo{}` on one line if there are no fields
|
||||||
f.write('$name{}')
|
f.write('$name{}')
|
||||||
} else if it.fields.len == 0 {
|
} else if it.fields.len == 0 {
|
||||||
// `Foo{1,2,3}` (short syntax )
|
// `Foo{1,2,3}` (short syntax )
|
||||||
f.write('$name{')
|
f.write('$name{')
|
||||||
for i, expr in it.exprs {
|
for i, field in it.fields {
|
||||||
f.expr(expr)
|
f.expr(field.expr)
|
||||||
if i < it.exprs.len - 1 {
|
if i < it.fields.len - 1 {
|
||||||
f.write(', ')
|
f.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,8 +712,8 @@ fn (f mut Fmt) expr(node ast.Expr) {
|
||||||
f.writeln('$name{')
|
f.writeln('$name{')
|
||||||
f.indent++
|
f.indent++
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
f.write('$field: ')
|
f.write('$field.name: ')
|
||||||
f.expr(it.exprs[i])
|
f.expr(field.expr)
|
||||||
f.writeln('')
|
f.writeln('')
|
||||||
}
|
}
|
||||||
f.indent--
|
f.indent--
|
||||||
|
|
|
@ -1918,22 +1918,22 @@ fn (var g Gen) struct_init(struct_init ast.StructInit) {
|
||||||
} else {
|
} else {
|
||||||
g.writeln('($styp){')
|
g.writeln('($styp){')
|
||||||
}
|
}
|
||||||
var fields := []string
|
// var fields := []string
|
||||||
var inited_fields := []string // TODO this is done in checker, move to ast node
|
var inited_fields := []string // TODO this is done in checker, move to ast node
|
||||||
if struct_init.fields.len == 0 && struct_init.exprs.len > 0 {
|
/*if struct_init.fields.len == 0 && struct_init.exprs.len > 0 {
|
||||||
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
|
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
|
||||||
for f in info.fields {
|
for f in info.fields {
|
||||||
fields << f.name
|
fields << f.name
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fields = struct_init.fields
|
fields = struct_init.fields
|
||||||
}
|
}*/
|
||||||
// User set fields
|
// User set fields
|
||||||
for i, field in fields {
|
for i, field in struct_init.fields {
|
||||||
field_name := c_name(field)
|
field_name := c_name(field.name)
|
||||||
inited_fields << field
|
inited_fields << field.name
|
||||||
g.write('\t.$field_name = ')
|
g.write('\t.$field_name = ')
|
||||||
g.expr_with_cast(struct_init.exprs[i], struct_init.expr_types[i], struct_init.expected_types[i])
|
g.expr_with_cast(field.expr, field.typ, field.expected_type)
|
||||||
g.writeln(',')
|
g.writeln(',')
|
||||||
}
|
}
|
||||||
// The rest of the fields are zeroed.
|
// The rest of the fields are zeroed.
|
||||||
|
|
|
@ -964,8 +964,8 @@ fn (g mut JsGen) gen_struct_init(it ast.StructInit) {
|
||||||
g.writeln('new ${type_sym.name}({')
|
g.writeln('new ${type_sym.name}({')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('$field: ')
|
g.write('$field.name: ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(field.expr)
|
||||||
if i < it.fields.len - 1 {
|
if i < it.fields.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,6 +570,7 @@ pub fn (var p Parser) parse_ident(is_c, is_js bool) ast.Ident {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
|
first_pos := p.tok.position()
|
||||||
typ := if short_syntax { table.void_type } else { p.parse_type() }
|
typ := if short_syntax { table.void_type } else { p.parse_type() }
|
||||||
p.expr_mod = ''
|
p.expr_mod = ''
|
||||||
// sym := p.table.get_type_symbol(typ)
|
// sym := p.table.get_type_symbol(typ)
|
||||||
|
@ -577,8 +578,7 @@ fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
if !short_syntax {
|
if !short_syntax {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
}
|
}
|
||||||
var field_names := []string
|
var fields := []ast.StructInitField
|
||||||
var exprs := []ast.Expr
|
|
||||||
var i := 0
|
var i := 0
|
||||||
is_short_syntax := p.peek_tok.kind != .colon && p.tok.kind != .rcbr // `Vec{a,b,c}
|
is_short_syntax := p.peek_tok.kind != .colon && p.tok.kind != .rcbr // `Vec{a,b,c}
|
||||||
// p.warn(is_short_syntax.str())
|
// p.warn(is_short_syntax.str())
|
||||||
|
@ -587,15 +587,27 @@ fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
var field_name := ''
|
var field_name := ''
|
||||||
if is_short_syntax {
|
if is_short_syntax {
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
exprs << expr
|
fields << ast.StructInitField{
|
||||||
} else {
|
// name will be set later in checker
|
||||||
field_name = p.check_name()
|
expr: expr
|
||||||
field_names << field_name
|
pos: expr.position()
|
||||||
}
|
}
|
||||||
if !is_short_syntax {
|
} else {
|
||||||
|
first_field_pos := p.tok.position()
|
||||||
|
field_name = p.check_name()
|
||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
exprs << expr
|
last_field_pos := expr.position()
|
||||||
|
field_pos := token.Position{
|
||||||
|
line_nr: first_field_pos.line_nr
|
||||||
|
pos: first_field_pos.pos
|
||||||
|
len: last_field_pos.pos - first_field_pos.pos + last_field_pos.len
|
||||||
|
}
|
||||||
|
fields << ast.StructInitField{
|
||||||
|
name: field_name
|
||||||
|
expr: expr
|
||||||
|
pos: field_pos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
|
@ -603,15 +615,20 @@ fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
}
|
}
|
||||||
p.check_comment()
|
p.check_comment()
|
||||||
}
|
}
|
||||||
node := ast.StructInit{
|
last_pos := p.tok.position()
|
||||||
typ: typ
|
|
||||||
exprs: exprs
|
|
||||||
fields: field_names
|
|
||||||
pos: p.tok.position()
|
|
||||||
}
|
|
||||||
if !short_syntax {
|
if !short_syntax {
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
}
|
}
|
||||||
|
node := ast.StructInit{
|
||||||
|
typ: typ
|
||||||
|
fields: fields
|
||||||
|
pos: token.Position{
|
||||||
|
line_nr: first_pos.line_nr
|
||||||
|
pos: first_pos.pos
|
||||||
|
len: last_pos.pos - first_pos.pos + last_pos.len
|
||||||
|
}
|
||||||
|
is_short: is_short_syntax
|
||||||
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue