v2: handle var decl & assign stmt together 1st step combining
parent
8c43644301
commit
c4b9ef388f
|
@ -229,8 +229,9 @@ pub mut:
|
|||
|
||||
pub struct IdentVar {
|
||||
pub mut:
|
||||
typ table.Type
|
||||
is_mut bool
|
||||
typ table.Type
|
||||
is_mut bool
|
||||
is_static bool
|
||||
}
|
||||
|
||||
type IdentInfo = IdentFunc | IdentVar
|
||||
|
|
|
@ -63,6 +63,14 @@ pub fn (s mut Scope) override_var(var VarDecl) {
|
|||
s.vars[var.name] = var
|
||||
}
|
||||
|
||||
pub fn (s &Scope) outermost() &Scope {
|
||||
mut sc := s
|
||||
for !isnil(sc.parent) {
|
||||
sc = sc.parent
|
||||
}
|
||||
return sc
|
||||
}
|
||||
|
||||
// returns the innermost scope containing pos
|
||||
pub fn (s &Scope) innermost(pos int) ?&Scope {
|
||||
if s.contains(pos) {
|
||||
|
|
|
@ -538,8 +538,14 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
|||
// Handle indents with unresolved types during the parsing step
|
||||
// (declared after first usage)
|
||||
else if ident.kind == .unresolved {
|
||||
// prepend mod to look for fn call or const
|
||||
mut name := ident.name
|
||||
if !name.contains('.') && !(c.file.mod.name in ['builtin', 'main']) {
|
||||
name = '${c.file.mod.name}.$ident.name'
|
||||
}
|
||||
// println('# name: $name')
|
||||
// constant
|
||||
if constant := c.table.find_const(ident.name) {
|
||||
if constant := c.table.find_const(name) {
|
||||
ident.kind = .constant
|
||||
ident.info = ast.IdentVar{
|
||||
typ: constant.typ
|
||||
|
@ -547,7 +553,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
|||
return constant.typ
|
||||
}
|
||||
// Function object (not a call), e.g. `onclick(my_click)`
|
||||
if func := c.table.find_fn(ident.name) {
|
||||
if func := c.table.find_fn(name) {
|
||||
ident.kind = .function
|
||||
ident.info = ast.IdentFunc{
|
||||
return_type: func.return_type
|
||||
|
@ -564,8 +570,10 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
|||
pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
|
||||
t := c.expr(node.cond)
|
||||
for i, block in node.blocks {
|
||||
match_expr := node.match_exprs[i]
|
||||
c.expr(match_expr)
|
||||
if i < node.match_exprs.len {
|
||||
match_expr := node.match_exprs[i]
|
||||
c.expr(match_expr)
|
||||
}
|
||||
for stmt in block.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
|
@ -680,6 +688,10 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type {
|
|||
return info.value_type
|
||||
}
|
||||
else if typ_sym.kind in [.byteptr, .string] {
|
||||
// TODO: hack need to handle &a[0] comment to see wyahsh errors
|
||||
if typ_sym.kind == .byteptr {
|
||||
return table.type_to_ptr(table.byte_type)
|
||||
}
|
||||
return table.byte_type
|
||||
}
|
||||
// else {
|
||||
|
|
|
@ -24,7 +24,7 @@ fn main() {
|
|||
mut d := testb(1)
|
||||
d = 'hello'
|
||||
|
||||
mut e = 'hello'
|
||||
mut e := 'hello'
|
||||
e = testb(111)
|
||||
e = 'world'
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||
}
|
||||
}
|
||||
.key_mut {
|
||||
return p.var_decl()
|
||||
return p.var_decl_and_assign_stmt()
|
||||
}
|
||||
.key_for {
|
||||
return p.for_statement()
|
||||
|
@ -313,12 +313,8 @@ 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] {
|
||||
return p.var_decl()
|
||||
}
|
||||
else if p.tok.kind == .name && p.peek_tok.kind in [.comma] {
|
||||
return p.assign_stmt()
|
||||
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
||||
return p.var_decl_and_assign_stmt()
|
||||
}
|
||||
// `label:`
|
||||
else if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
||||
|
@ -339,6 +335,7 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: merge wtih AssignStmt & VarDecl
|
||||
pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
||||
op := p.tok.kind
|
||||
p.next()
|
||||
|
@ -456,40 +453,32 @@ pub fn (p &Parser) warn(s string) {
|
|||
|
||||
pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
|
||||
// p.warn('name ')
|
||||
// left := p.parse_ident()
|
||||
name := p.check_name()
|
||||
mut name := p.check_name()
|
||||
if name == '_' {
|
||||
return ast.Ident{
|
||||
name: '_'
|
||||
kind: .blank_ident
|
||||
pos: p.tok.position()
|
||||
}
|
||||
}
|
||||
if p.expr_mod.len > 0 {
|
||||
name = '${p.expr_mod}.$name'
|
||||
}
|
||||
mut ident := ast.Ident{
|
||||
kind: .unresolved
|
||||
name: name
|
||||
is_c: is_c
|
||||
pos: p.tok.position()
|
||||
}
|
||||
mut known_var := false
|
||||
if var := p.scope.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{}
|
||||
return ident
|
||||
}
|
||||
else {
|
||||
// handle consts/fns in checker
|
||||
ident.kind = .unresolved
|
||||
return {
|
||||
ident |
|
||||
name:p.prepend_mod(name)
|
||||
if p.expr_mod.len == 0 {
|
||||
if var := p.scope.find_var(name) {
|
||||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{}
|
||||
}
|
||||
}
|
||||
// handle consts/fns in checker
|
||||
return ident
|
||||
}
|
||||
|
||||
fn (p mut Parser) struct_init() ast.StructInit {
|
||||
|
@ -565,7 +554,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
|
|||
map_type := p.parse_map_type()
|
||||
return node
|
||||
}
|
||||
if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit)) {
|
||||
if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit) || p.mod.all_after('.') == p.tok.lit) {
|
||||
if !is_c {
|
||||
// prepend the full import
|
||||
mod = p.imports[p.tok.lit]
|
||||
|
@ -998,11 +987,8 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||
mut init := ast.Stmt{}
|
||||
mut cond := ast.Expr{}
|
||||
mut inc := ast.Stmt{}
|
||||
if p.peek_tok.kind == .decl_assign {
|
||||
init = p.var_decl()
|
||||
}
|
||||
else if p.peek_tok.kind == .assign {
|
||||
init = p.assign_stmt()
|
||||
if p.peek_tok.kind in [.assign, .decl_assign] {
|
||||
init = p.var_decl_and_assign_stmt()
|
||||
}
|
||||
else if p.tok.kind != .semicolon {}
|
||||
// allow `for ;; i++ {`
|
||||
|
@ -1528,11 +1514,23 @@ fn (p mut Parser) return_stmt() ast.Return {
|
|||
return stmt
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||
// TODO: multiple return & multiple assign
|
||||
// left hand side of `=` or `:=` in `a,b,c := 1,2,3`
|
||||
fn (p mut Parser) parse_assign_lhs() []ast.Ident {
|
||||
mut idents := []ast.Ident
|
||||
for {
|
||||
ident := p.parse_ident(false)
|
||||
is_mut := p.tok.kind == .key_mut
|
||||
if is_mut {
|
||||
p.check(.key_mut)
|
||||
}
|
||||
is_static := p.tok.kind == .key_static
|
||||
if is_static {
|
||||
p.check(.key_static)
|
||||
}
|
||||
mut ident := p.parse_ident(false)
|
||||
ident.info = ast.IdentVar{
|
||||
is_mut: is_mut
|
||||
is_static: is_static
|
||||
}
|
||||
idents << ident
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
|
@ -1541,10 +1539,63 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
|||
break
|
||||
}
|
||||
}
|
||||
return idents
|
||||
}
|
||||
|
||||
// right hand side of `=` or `:=` in `a,b,c := 1,2,3`
|
||||
fn (p mut Parser) parse_assign_rhs() []ast.Expr {
|
||||
mut exprs := []ast.Expr
|
||||
for {
|
||||
expr,_ := p.expr(0)
|
||||
exprs << expr
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
}
|
||||
else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return exprs
|
||||
}
|
||||
|
||||
fn (p mut Parser) var_decl_and_assign_stmt() ast.Stmt {
|
||||
idents := p.parse_assign_lhs()
|
||||
op := p.tok.kind
|
||||
p.next() // :=, =
|
||||
expr,_ := p.expr(0)
|
||||
exprs := p.parse_assign_rhs()
|
||||
is_decl := op == .decl_assign
|
||||
// VarDecl
|
||||
if idents.len == 1 {
|
||||
ident := idents[0]
|
||||
expr := exprs[0]
|
||||
info0 := ident.var_info()
|
||||
known_var := p.scope.known_var(ident.name)
|
||||
if !is_decl && !known_var {
|
||||
p.error('unknown variable `$ident.name`')
|
||||
}
|
||||
if is_decl && ident.kind != .blank_ident {
|
||||
if known_var {
|
||||
p.error('redefinition of `$ident.name`')
|
||||
}
|
||||
p.scope.register_var(ast.VarDecl{
|
||||
name: ident.name
|
||||
expr: expr
|
||||
})
|
||||
}
|
||||
return ast.VarDecl{
|
||||
name: ident.name
|
||||
// name2: name2
|
||||
|
||||
expr: expr // p.expr(token.lowest_prec)
|
||||
|
||||
is_mut: info0.is_mut
|
||||
// typ: typ
|
||||
|
||||
pos: p.tok.position()
|
||||
}
|
||||
// return p.var_decl(ident[0], exprs[0])
|
||||
}
|
||||
// AssignStmt
|
||||
for ident in idents {
|
||||
if is_decl && ident.kind != .blank_ident {
|
||||
if p.scope.known_var(ident.name) {
|
||||
|
@ -1557,65 +1608,14 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
|||
}
|
||||
return ast.AssignStmt{
|
||||
left: idents
|
||||
right: [expr]
|
||||
right: exprs
|
||||
op: op
|
||||
pos: p.tok.position()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
if p.tok.kind == .key_mut {
|
||||
p.check(.key_mut)
|
||||
// p.fspace()
|
||||
}
|
||||
if p.tok.kind == .key_static {
|
||||
p.check(.key_static)
|
||||
// p.fspace()
|
||||
}
|
||||
name := p.check_name()
|
||||
mut name2 := ''
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
name2 = p.check_name()
|
||||
}
|
||||
p.next() // :=
|
||||
// expr,typ := p.expr(0)
|
||||
expr,_ := p.expr(0)
|
||||
// if _ := p.table.find_var(name) {
|
||||
// p.error('redefinition of `$name`')
|
||||
// }
|
||||
// p.table.register_var(table.Var{
|
||||
// name: name
|
||||
// is_mut: is_mut
|
||||
// typ: typ
|
||||
// })
|
||||
if _ := p.scope.find_var(name) {
|
||||
p.error('redefinition of `$name`')
|
||||
}
|
||||
// p.scope.register_var(table.Var{
|
||||
// name: name
|
||||
// is_mut: is_mut
|
||||
// typ: typ
|
||||
// })
|
||||
// typ_sym := p.table.get_type_symbol(typ)
|
||||
// p.warn('var decl name=$name typ=$typ_sym.name')
|
||||
// println(p.table.names)
|
||||
node := ast.VarDecl{
|
||||
name: name
|
||||
name2: name2
|
||||
expr: expr // p.expr(token.lowest_prec)
|
||||
|
||||
is_mut: is_mut
|
||||
// typ: typ
|
||||
|
||||
pos: p.tok.position()
|
||||
}
|
||||
p.scope.register_var(node)
|
||||
return node
|
||||
}
|
||||
|
||||
// pub fn (p mut Parser) assign_stmt() ast.AssignStmt {}
|
||||
// fn (p mut Parser) var_decl() ast.VarDecl {}
|
||||
fn (p mut Parser) hash() ast.HashStmt {
|
||||
p.next()
|
||||
return ast.HashStmt{
|
||||
|
|
|
@ -370,6 +370,10 @@ pub fn (t &Table) check(got, expected Type) bool {
|
|||
if got_type_sym.is_number() && exp_type_sym.is_number() {
|
||||
return true
|
||||
}
|
||||
// check hack in checker IndexExpr line #691
|
||||
if type_is_ptr(got) && got_type_sym.kind == .byte && exp_type_sym.kind == .byteptr {
|
||||
return true
|
||||
}
|
||||
// TODO
|
||||
// if got_type_sym.kind == .array && exp_type_sym.kind == .array {
|
||||
// return true
|
||||
|
|
|
@ -98,7 +98,7 @@ pub fn new_type_ptr(idx int, nr_muls int) Type {
|
|||
}
|
||||
|
||||
pub const (
|
||||
number_idxs = [int_type_idx, byte_type_idx, u64_type_idx]
|
||||
number_idxs = [int_type_idx, byte_type_idx, u32_type_idx, u64_type_idx]
|
||||
)
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue