mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: start impl multi assign
This commit is contained in:
parent
65744207fc
commit
67a13fc916
@ -14,7 +14,7 @@ AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr
|
|||||||
|
|
||||||
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
|
HashStmt | AssignStmt
|
||||||
// | IncDecStmt k
|
// | IncDecStmt k
|
||||||
// Stand-alone expression in a statement list.
|
// Stand-alone expression in a statement list.
|
||||||
pub struct ExprStmt {
|
pub struct ExprStmt {
|
||||||
@ -196,6 +196,7 @@ pub:
|
|||||||
pub struct IdentVar {
|
pub struct IdentVar {
|
||||||
pub mut:
|
pub mut:
|
||||||
typ table.TypeRef
|
typ table.TypeRef
|
||||||
|
is_mut bool
|
||||||
//name string
|
//name string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +206,7 @@ pub enum IdentKind {
|
|||||||
blank_ident
|
blank_ident
|
||||||
variable
|
variable
|
||||||
constant
|
constant
|
||||||
|
func
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single identifier
|
// A single identifier
|
||||||
@ -219,6 +221,18 @@ mut:
|
|||||||
info IdentInfo
|
info IdentInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn(i &Ident) var_info() IdentVar {
|
||||||
|
match i.info {
|
||||||
|
IdentVar {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// return IdentVar{}
|
||||||
|
panic('Ident.var_info(): info is not IdentVar variant')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InfixExpr {
|
pub struct InfixExpr {
|
||||||
pub:
|
pub:
|
||||||
// op BinaryOp
|
// op BinaryOp
|
||||||
@ -326,14 +340,14 @@ pub:
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub struct AssignStmt {
|
pub struct AssignStmt {
|
||||||
pub:
|
pub:
|
||||||
left Expr
|
left []Ident
|
||||||
right Expr
|
right []Expr
|
||||||
op token.Kind
|
op token.Kind
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// e.g. `[unsafe_fn]`
|
// e.g. `[unsafe_fn]`
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
|
@ -46,7 +46,7 @@ fn (c mut Checker) resolve_types() {
|
|||||||
// update any types with unresolved sub types
|
// update any types with unresolved sub types
|
||||||
for idx, t in c.table.types {
|
for idx, t in c.table.types {
|
||||||
if t.kind == .array {
|
if t.kind == .array {
|
||||||
mut info := t.info as table.Array
|
mut info := t.array_info()
|
||||||
if info.elem_type.typ.kind == .unresolved {
|
if info.elem_type.typ.kind == .unresolved {
|
||||||
info.elem_type = c.resolved[info.elem_type.idx]
|
info.elem_type = c.resolved[info.elem_type.idx]
|
||||||
mut t1 := &c.table.types[idx]
|
mut t1 := &c.table.types[idx]
|
||||||
@ -55,7 +55,7 @@ fn (c mut Checker) resolve_types() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if t.kind == .map {
|
else if t.kind == .map {
|
||||||
mut info := t.info as table.Map
|
mut info := t.map_info()
|
||||||
mut updated := false
|
mut updated := false
|
||||||
if info.key_type.typ.kind == .unresolved {
|
if info.key_type.typ.kind == .unresolved {
|
||||||
info.key_type = c.resolved[info.key_type.idx]
|
info.key_type = c.resolved[info.key_type.idx]
|
||||||
@ -71,6 +71,22 @@ fn (c mut Checker) resolve_types() {
|
|||||||
t1.info = info
|
t1.info = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if t.kind == .multi_return {
|
||||||
|
mut info := t.mr_info()
|
||||||
|
mut types := info.types
|
||||||
|
mut updated := false
|
||||||
|
for i, ut in types {
|
||||||
|
if ut.typ.kind == .unresolved {
|
||||||
|
types[i] = c.resolved[ut.idx]
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
mut t1 := &c.table.types[idx]
|
||||||
|
info.types = types
|
||||||
|
t1.info = info
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +213,8 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {}
|
||||||
|
|
||||||
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef {
|
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.TypeRef {
|
||||||
mut elem_type := c.table.type_ref(table.void_type_idx)
|
mut elem_type := c.table.type_ref(table.void_type_idx)
|
||||||
for i, expr in array_init.exprs {
|
for i, expr in array_init.exprs {
|
||||||
@ -224,6 +242,9 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||||||
ast.Return {
|
ast.Return {
|
||||||
c.return_stmt(it)
|
c.return_stmt(it)
|
||||||
}
|
}
|
||||||
|
ast.AssignStmt {
|
||||||
|
c.assign_stmt(it)
|
||||||
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
typ := c.expr(it.expr)
|
typ := c.expr(it.expr)
|
||||||
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
||||||
|
@ -106,6 +106,23 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
ast.AssignStmt {
|
||||||
|
// ident0 := it.left[0]
|
||||||
|
// info0 := ident0.var_info()
|
||||||
|
// for i, ident in it.left {
|
||||||
|
// info := ident.var_info()
|
||||||
|
// if info0.typ.typ.kind == .multi_return {
|
||||||
|
// if i == 0 {
|
||||||
|
// g.write('$info.typ.typ.name $ident.name = ')
|
||||||
|
// g.expr(it.right[0])
|
||||||
|
// } else {
|
||||||
|
// arg_no := i-1
|
||||||
|
// g.write('$info.typ.typ.name $ident.name = $ident0.name->arg[$arg_no]')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// g.writeln(';')
|
||||||
|
// }
|
||||||
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.typ.typ.name $it.name = ')
|
g.write('$it.typ.typ.name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
|
@ -55,6 +55,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
ast.AssignStmt {}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('var /* $it.typ.typ.name */ $it.name = ')
|
g.write('var /* $it.typ.typ.name */ $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
multi_return_int_string mr_test();
|
||||||
int testa();
|
int testa();
|
||||||
string testb(int a);
|
string testb(int a);
|
||||||
int testc(int a);
|
int testc(int a);
|
||||||
int testa();
|
int testa();
|
||||||
int testb();
|
int testb();
|
||||||
int testa();
|
int testa();
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Bar b = (Bar){
|
Bar b = (Bar){
|
||||||
.a = 122,
|
.a = 122,
|
||||||
@ -32,6 +34,10 @@ int main() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multi_return_int_string mr_test() {
|
||||||
|
return (multi_return_int_string){.arg0=1,.arg1=tos3("v")};
|
||||||
|
}
|
||||||
|
|
||||||
int testa() {
|
int testa() {
|
||||||
return testc(1);
|
return testc(1);
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,13 @@ fn main() {
|
|||||||
|
|
||||||
mut f := [testa(),2,3,4]
|
mut f := [testa(),2,3,4]
|
||||||
mut g := [testb(1),'hello']
|
mut g := [testb(1),'hello']
|
||||||
|
|
||||||
|
m1, m2 := mr_test()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mr_test() (int, string) {
|
||||||
|
return 1,'v'
|
||||||
|
}
|
||||||
|
|
||||||
fn testa() int {
|
fn testa() int {
|
||||||
return testc(1)
|
return testc(1)
|
||||||
|
@ -326,6 +326,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||||||
g.ret()
|
g.ret()
|
||||||
}
|
}
|
||||||
ast.Return {}
|
ast.Return {}
|
||||||
|
ast.AssignStmt {}
|
||||||
ast.VarDecl {}
|
ast.VarDecl {}
|
||||||
ast.ForStmt {}
|
ast.ForStmt {}
|
||||||
ast.StructDecl {}
|
ast.StructDecl {}
|
||||||
|
@ -242,9 +242,13 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// `x := ...`
|
// `x := ...`
|
||||||
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
// if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
||||||
|
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign] {
|
||||||
return p.var_decl()
|
return p.var_decl()
|
||||||
}
|
}
|
||||||
|
if p.tok.kind == .name && p.peek_tok.kind in [.comma] {
|
||||||
|
return p.assign_stmt()
|
||||||
|
}
|
||||||
expr,typ := p.expr(0)
|
expr,typ := p.expr(0)
|
||||||
return ast.ExprStmt{
|
return ast.ExprStmt{
|
||||||
expr: expr
|
expr: expr
|
||||||
@ -370,6 +374,60 @@ pub fn (p &Parser) warn(s string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) {
|
||||||
|
mut node := ast.Ident{}
|
||||||
|
mut typ := p.table.type_ref(table.void_type_idx)
|
||||||
|
// p.warn('name ')
|
||||||
|
// left := p.parse_ident()
|
||||||
|
name := p.check_name()
|
||||||
|
mut ident := ast.Ident{
|
||||||
|
name: name
|
||||||
|
}
|
||||||
|
mut known_var := false
|
||||||
|
if var := p.table.find_var(name) {
|
||||||
|
known_var = true
|
||||||
|
typ = var.typ
|
||||||
|
}
|
||||||
|
// variable
|
||||||
|
if known_var || p.tok.kind in [.comma, .decl_assign, .assign] {
|
||||||
|
// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
|
||||||
|
ident.kind = .variable
|
||||||
|
ident.info = ast.IdentVar{
|
||||||
|
typ: typ
|
||||||
|
// name: ident.name
|
||||||
|
// expr: p.expr(0)// var.expr
|
||||||
|
}
|
||||||
|
return ident, typ
|
||||||
|
}else{
|
||||||
|
if is_c {
|
||||||
|
typ = p.table.type_ref(table.int_type_idx)
|
||||||
|
ident.info = ast.IdentVar{
|
||||||
|
typ: typ
|
||||||
|
// name: ident.name
|
||||||
|
}
|
||||||
|
return ident,typ
|
||||||
|
}
|
||||||
|
// const
|
||||||
|
if c := p.table.find_const(name) {
|
||||||
|
typ = c.typ
|
||||||
|
ident.kind = .constant
|
||||||
|
ident.info = ast.IdentVar{
|
||||||
|
typ: typ
|
||||||
|
// name: ident.name
|
||||||
|
}
|
||||||
|
node = ident
|
||||||
|
}else{
|
||||||
|
// Function object (not a call), e.g. `onclick(my_click)`
|
||||||
|
p.table.find_fn(name) or {
|
||||||
|
p.error('parse_ident: unknown identifier `$name`')
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
// p.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node, typ
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
|
pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
mut typ := p.table.type_ref(table.void_type_idx)
|
mut typ := p.table.type_ref(table.void_type_idx)
|
||||||
@ -425,54 +483,9 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
|
|||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// p.warn('name ')
|
mut ident := ast.Ident{}
|
||||||
// left := p.parse_ident()
|
ident, typ = p.parse_ident(is_c)
|
||||||
mut ident := ast.Ident{
|
|
||||||
name: p.tok.lit
|
|
||||||
}
|
|
||||||
// variable
|
|
||||||
if var := p.table.find_var(p.tok.lit) {
|
|
||||||
// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
|
|
||||||
typ = var.typ
|
|
||||||
ident.kind = .variable
|
|
||||||
ident.info = ast.IdentVar{
|
|
||||||
typ: typ
|
|
||||||
// name: ident.name
|
|
||||||
// expr: p.expr(0)// var.expr
|
|
||||||
}
|
|
||||||
// ident.ti = ti
|
|
||||||
node = ident
|
node = ident
|
||||||
p.next()
|
|
||||||
}else{
|
|
||||||
if is_c {
|
|
||||||
typ = p.table.type_ref(table.int_type_idx)
|
|
||||||
ident.info = ast.IdentVar{
|
|
||||||
typ: typ
|
|
||||||
// name: ident.name
|
|
||||||
}
|
|
||||||
node = ident
|
|
||||||
p.next()
|
|
||||||
return node,typ
|
|
||||||
}
|
|
||||||
// const
|
|
||||||
if c := p.table.find_const(p.tok.lit) {
|
|
||||||
typ = c.typ
|
|
||||||
ident.kind = .constant
|
|
||||||
ident.info = ast.IdentVar{
|
|
||||||
typ: typ
|
|
||||||
// name: ident.name
|
|
||||||
}
|
|
||||||
node = ident
|
|
||||||
p.next()
|
|
||||||
}else{
|
|
||||||
// Function object (not a call), e.g. `onclick(my_click)`
|
|
||||||
p.table.find_fn(p.tok.lit) or {
|
|
||||||
p.error('name expr unknown identifier `$p.tok.lit`')
|
|
||||||
exit(0)
|
|
||||||
}
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return node,typ
|
return node,typ
|
||||||
}
|
}
|
||||||
@ -1047,7 +1060,6 @@ fn (p mut Parser) return_stmt() ast.Return {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: consider non deferred
|
|
||||||
stmt := ast.Return{
|
stmt := ast.Return{
|
||||||
expected_type: p.return_type
|
expected_type: p.return_type
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
@ -1056,6 +1068,26 @@ fn (p mut Parser) return_stmt() ast.Return {
|
|||||||
return stmt
|
return stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||||
|
// TODO: multiple return & multiple assign
|
||||||
|
mut idents := []ast.Ident
|
||||||
|
for {
|
||||||
|
ident, _ := p.parse_ident(false)
|
||||||
|
idents << ident
|
||||||
|
if p.tok.kind == .comma {
|
||||||
|
p.check(.comma)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.next() // :=, =
|
||||||
|
expr, _ := p.expr(0)
|
||||||
|
return ast.AssignStmt{
|
||||||
|
left: idents
|
||||||
|
right: [expr]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (p mut Parser) var_decl() ast.VarDecl {
|
fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for
|
is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for
|
||||||
// is_static := p.tok.kind == .key_static
|
// is_static := p.tok.kind == .key_static
|
||||||
@ -1076,8 +1108,6 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
|||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: name
|
name: name
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
// expr: expr
|
|
||||||
|
|
||||||
typ: typ
|
typ: typ
|
||||||
})
|
})
|
||||||
p.warn('var decl name=$name typ=$typ.typ.name')
|
p.warn('var decl name=$name typ=$typ.typ.name')
|
||||||
@ -1170,7 +1200,7 @@ fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.TypeRef {
|
|||||||
typ: &table.Type{
|
typ: &table.Type{
|
||||||
parent: 0
|
parent: 0
|
||||||
kind: .unresolved
|
kind: .unresolved
|
||||||
name: 'unresolved $p.unresolved.len'
|
name: 'unresolved $idx'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -77,6 +77,54 @@ pub enum Kind {
|
|||||||
unresolved
|
unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn(t &Type) mr_info() MultiReturn {
|
||||||
|
match t.info {
|
||||||
|
MultiReturn {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('Type.mr_info(): no multi return info')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn(t &Type) array_info() Array {
|
||||||
|
match t.info {
|
||||||
|
Array {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('Type.mr_info(): no array info')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn(t &Type) array_fixed_info() ArrayFixed {
|
||||||
|
match t.info {
|
||||||
|
ArrayFixed {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('Type.mr_info(): no array fixed info')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn(t &Type) map_info() Map {
|
||||||
|
match t.info {
|
||||||
|
Map {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('Type.mr_info(): no map info')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (t Type) str() string {
|
pub fn (t Type) str() string {
|
||||||
return t.name
|
return t.name
|
||||||
@ -395,6 +443,7 @@ pub mut:
|
|||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
mut:
|
||||||
types []TypeRef
|
types []TypeRef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user