v2: start impl multi assign

pull/3669/head
joe-conigliaro 2020-02-07 03:38:02 +11:00 committed by GitHub
parent 65744207fc
commit 67a13fc916
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 206 additions and 62 deletions

View File

@ -14,7 +14,7 @@ AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
HashStmt
HashStmt | AssignStmt
// | IncDecStmt k
// Stand-alone expression in a statement list.
pub struct ExprStmt {
@ -195,7 +195,8 @@ pub:
pub struct IdentVar {
pub mut:
typ table.TypeRef
typ table.TypeRef
is_mut bool
//name string
}
@ -205,6 +206,7 @@ pub enum IdentKind {
blank_ident
variable
constant
func
}
// A single identifier
@ -219,6 +221,18 @@ mut:
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:
// op BinaryOp
@ -326,14 +340,14 @@ pub:
name string
}
/*
pub struct AssignStmt {
pub:
left Expr
right Expr
left []Ident
right []Expr
op token.Kind
}
*/
// e.g. `[unsafe_fn]`
pub struct Attr {

View File

@ -46,7 +46,7 @@ fn (c mut Checker) resolve_types() {
// update any types with unresolved sub types
for idx, t in c.table.types {
if t.kind == .array {
mut info := t.info as table.Array
mut info := t.array_info()
if info.elem_type.typ.kind == .unresolved {
info.elem_type = c.resolved[info.elem_type.idx]
mut t1 := &c.table.types[idx]
@ -55,7 +55,7 @@ fn (c mut Checker) resolve_types() {
}
}
else if t.kind == .map {
mut info := t.info as table.Map
mut info := t.map_info()
mut updated := false
if info.key_type.typ.kind == .unresolved {
info.key_type = c.resolved[info.key_type.idx]
@ -71,6 +71,22 @@ fn (c mut Checker) resolve_types() {
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 {
mut elem_type := c.table.type_ref(table.void_type_idx)
for i, expr in array_init.exprs {
@ -224,6 +242,9 @@ fn (c &Checker) stmt(node ast.Stmt) {
ast.Return {
c.return_stmt(it)
}
ast.AssignStmt {
c.assign_stmt(it)
}
ast.VarDecl {
typ := c.expr(it.expr)
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')

View File

@ -106,6 +106,23 @@ fn (g mut Gen) stmt(node ast.Stmt) {
}
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 {
g.write('$it.typ.typ.name $it.name = ')
g.expr(it.expr)

View File

@ -55,6 +55,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
}
g.writeln(';')
}
ast.AssignStmt {}
ast.VarDecl {
g.write('var /* $it.typ.typ.name */ $it.name = ')
g.expr(it.expr)

View File

@ -1,9 +1,11 @@
multi_return_int_string mr_test();
int testa();
string testb(int a);
int testc(int a);
int testa();
int testb();
int testa();
int main() {
Bar b = (Bar){
.a = 122,
@ -29,7 +31,11 @@ int main() {
array_string g = new_array_from_c_array(2, 2, sizeof(array_string), {
testb(1), tos3("hello"),
});
return 0;
return 0;
}
multi_return_int_string mr_test() {
return (multi_return_int_string){.arg0=1,.arg1=tos3("v")};
}
int testa() {

View File

@ -30,8 +30,13 @@ fn main() {
mut f := [testa(),2,3,4]
mut g := [testb(1),'hello']
m1, m2 := mr_test()
}
fn mr_test() (int, string) {
return 1,'v'
}
fn testa() int {
return testc(1)

View File

@ -326,6 +326,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.ret()
}
ast.Return {}
ast.AssignStmt {}
ast.VarDecl {}
ast.ForStmt {}
ast.StructDecl {}

View File

@ -242,9 +242,13 @@ pub fn (p mut Parser) stmt() ast.Stmt {
}
else {
// `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()
}
if p.tok.kind == .name && p.peek_tok.kind in [.comma] {
return p.assign_stmt()
}
expr,typ := p.expr(0)
return ast.ExprStmt{
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) {
mut node := ast.Expr{}
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)
}
else {
// p.warn('name ')
// left := p.parse_ident()
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
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()
}
}
mut ident := ast.Ident{}
ident, typ = p.parse_ident(is_c)
node = ident
}
return node,typ
}
@ -1047,7 +1060,6 @@ fn (p mut Parser) return_stmt() ast.Return {
break
}
}
// TODO: consider non deferred
stmt := ast.Return{
expected_type: p.return_type
exprs: exprs
@ -1056,6 +1068,26 @@ fn (p mut Parser) return_stmt() ast.Return {
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 {
is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for
// 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{
name: name
is_mut: is_mut
// expr: expr
typ: typ
})
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{
parent: 0
kind: .unresolved
name: 'unresolved $p.unresolved.len'
name: 'unresolved $idx'
}
}
return t

View File

@ -77,6 +77,54 @@ pub enum Kind {
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 {
return t.name
@ -395,6 +443,7 @@ pub mut:
pub struct MultiReturn {
pub:
name string
mut:
types []TypeRef
}