v2: scopes, or, in, hex

pull/3652/head
Alexander Medvednikov 2020-02-04 17:44:39 +01:00
parent 9b60a50d07
commit 80daaff874
8 changed files with 153 additions and 66 deletions

View File

@ -157,7 +157,7 @@ pub fn (n i64) hex() string {
hex := malloc(len) hex := malloc(len)
// QTODO // QTODO
//count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n) //count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
count := C.sprintf('%x', n) count := C.sprintf(charptr(hex), '0x%x', n)
return tos(hex, count) return tos(hex, count)
} }
@ -165,7 +165,7 @@ pub fn (n u64) hex() string {
len := if n >= u64(0) { n.str().len + 3 } else { 19 } len := if n >= u64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len) hex := malloc(len)
//count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n) //count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
count := C.sprintf('%x', n) count := C.sprintf(charptr(hex), '0x%lx', n)
return tos(hex, count) return tos(hex, count)
} }

View File

@ -108,3 +108,8 @@ fn test_int_alias() {
assert i + 10 == 12 assert i + 10 == 12
*/ */
} }
fn test_hex() {
x := u64(10)
assert x.hex() == '0xa'
}

View File

@ -123,8 +123,8 @@ fn (n mut mapnode) split_child(child_index int, y mut mapnode) {
} }
if !isnil(y.children) { if !isnil(y.children) {
z.children = &voidptr(malloc(children_bytes)) z.children = &voidptr(malloc(children_bytes))
for j := degree - 1; j >= 0; j-- { for jj := degree - 1; jj >= 0; jj-- {
z.children[j] = y.children[j + degree] z.children[jj] = y.children[jj + degree]
} }
} }
if isnil(n.children) { if isnil(n.children) {

View File

@ -195,6 +195,17 @@ struct RepIndex {
val_idx int val_idx int
} }
fn compare_rep_index(a, b &RepIndex) int {
if a.idx < b.idx {
return -1
}
if a.idx > b.idx {
return 1
}
return 0
}
fn (a mut []RepIndex) sort() { fn (a mut []RepIndex) sort() {
a.sort_with_compare(compare_rep_index) a.sort_with_compare(compare_rep_index)
} }
@ -207,16 +218,6 @@ fn (a RepIndex) < (b RepIndex) bool {
*/ */
fn compare_rep_index(a, b &RepIndex) int {
if a.idx < b.idx {
return -1
}
if a.idx > b.idx {
return 1
}
return 0
}
pub fn (s string) replace_each(vals []string) string { pub fn (s string) replace_each(vals []string) string {
if s.len == 0 || vals.len == 0 { if s.len == 0 || vals.len == 0 {
return s return s
@ -244,7 +245,8 @@ pub fn (s string) replace_each(vals []string) string {
// We need to remember both the position in the string, // We need to remember both the position in the string,
// and which rep/with pair it refers to. // and which rep/with pair it refers to.
idxs << RepIndex{ idxs << RepIndex{
idx,rep_i} idx:idx
val_idx:rep_i}
idx++ idx++
new_len += with.len - rep.len new_len += with.len - rep.len
} }

View File

@ -216,7 +216,8 @@ pub fn parse_iso(s string) Time {
} }
mm := pos / 3 + 1 mm := pos / 3 + 1
tmstr := malloc(s.len * 2) tmstr := malloc(s.len * 2)
count := int(C.sprintf(charptr(tmstr), '%s-%02d-%s %s'.str, fields[3].str, mm, fields[1].str, fields[4].str)) count := C.sprintf(charptr(tmstr), '%s-%02d-%s %s'.str, fields[3].str, mm,
fields[1].str, fields[4].str)
return parse(tos(tmstr, count)) return parse(tos(tmstr, count))
} }

View File

@ -21,6 +21,10 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
pos: tok.position() pos: tok.position()
} }
if p.tok.kind == .key_orelse {
p.next()
p.parse_block()
}
if f := p.table.find_fn(fn_name) { if f := p.table.find_fn(fn_name) {
return node,f.return_type return node,f.return_type
} }
@ -45,6 +49,7 @@ pub fn (p mut Parser) call_args() []ast.Expr {
} }
fn (p mut Parser) fn_decl() ast.FnDecl { fn (p mut Parser) fn_decl() ast.FnDecl {
p.table.clear_vars()
is_pub := p.tok.kind == .key_pub is_pub := p.tok.kind == .key_pub
if is_pub { if is_pub {
p.next() p.next()

View File

@ -32,6 +32,8 @@ mut:
// vars []string // vars []string
table &table.Table table &table.Table
return_type table.Type // current function's return type return_type table.Type // current function's return type
// scope_level int
// var_idx int
is_c bool is_c bool
// //
// prefix_parse_fns []PrefixParseFn // prefix_parse_fns []PrefixParseFn
@ -118,6 +120,7 @@ pub fn (p mut Parser) read_first_token() {
} }
pub fn (p mut Parser) parse_block() []ast.Stmt { pub fn (p mut Parser) parse_block() []ast.Stmt {
p.table.open_scope()
p.check(.lcbr) p.check(.lcbr)
mut stmts := []ast.Stmt mut stmts := []ast.Stmt
if p.tok.kind != .rcbr { if p.tok.kind != .rcbr {
@ -130,6 +133,7 @@ pub fn (p mut Parser) parse_block() []ast.Stmt {
} }
} }
p.check(.rcbr) p.check(.rcbr)
p.table.close_scope()
// println('nr exprs in block = $exprs.len') // println('nr exprs in block = $exprs.len')
return stmts return stmts
} }
@ -405,7 +409,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
} }
// variable // variable
if var := p.table.find_var(p.tok.lit) { if var := p.table.find_var(p.tok.lit) {
println('#### IDENT: $var.name: $var.typ.name - $var.typ.idx') // println('#### IDENT: $var.name: $var.typ.name - $var.typ.idx')
typ = var.typ typ = var.typ
ident.kind = .variable ident.kind = .variable
ident.info = ast.IdentVar{ ident.info = ast.IdentVar{
@ -592,6 +596,10 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.T
if p.tok.kind == .lpar { if p.tok.kind == .lpar {
p.next() p.next()
args := p.call_args() args := p.call_args()
if p.tok.kind == .key_orelse {
p.next()
p.parse_block()
}
mcall_expr := ast.MethodCallExpr{ mcall_expr := ast.MethodCallExpr{
expr: left expr: left
name: field_name name: field_name
@ -645,9 +653,12 @@ fn (p &Parser) is_addative() bool {
fn (p mut Parser) for_statement() ast.Stmt { fn (p mut Parser) for_statement() ast.Stmt {
p.check(.key_for) p.check(.key_for)
p.table.open_scope()
// defer { p.table.close_scope() }
// Infinite loop // Infinite loop
if p.tok.kind == .lcbr { if p.tok.kind == .lcbr {
stmts := p.parse_block() stmts := p.parse_block()
p.table.close_scope()
return ast.ForStmt{ return ast.ForStmt{
stmts: stmts stmts: stmts
pos: p.tok.position() pos: p.tok.position()
@ -685,6 +696,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
inc = p.stmt() inc = p.stmt()
} }
stmts := p.parse_block() stmts := p.parse_block()
p.table.close_scope()
return ast.ForCStmt{ return ast.ForCStmt{
stmts: stmts stmts: stmts
init: init init: init
@ -693,8 +705,16 @@ fn (p mut Parser) for_statement() ast.Stmt {
} }
} }
// `for i in vals`, `for i in start .. end` // `for i in vals`, `for i in start .. end`
else if p.peek_tok.kind == .key_in { else if p.peek_tok.kind == .key_in || p.peek_tok.kind == .comma {
var_name := p.check_name() var_name := p.check_name()
if p.tok.kind == .comma {
p.check(.comma)
val_name := p.check_name()
p.table.register_var(table.Var{
name: val_name
typ: table.int_type
})
}
p.check(.key_in) p.check(.key_in)
start := p.tok.lit.int() start := p.tok.lit.int()
p.expr(0) p.expr(0)
@ -708,6 +728,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
}) })
stmts := p.parse_block() stmts := p.parse_block()
// println('nr stmts=$stmts.len') // println('nr stmts=$stmts.len')
p.table.close_scope()
return ast.ForStmt{ return ast.ForStmt{
stmts: stmts stmts: stmts
pos: p.tok.position() pos: p.tok.position()
@ -716,6 +737,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
// `for cond {` // `for cond {`
cond,_ := p.expr(0) cond,_ := p.expr(0)
stmts := p.parse_block() stmts := p.parse_block()
p.table.close_scope()
return ast.ForStmt{ return ast.ForStmt{
cond: cond cond: cond
stmts: stmts stmts: stmts
@ -735,8 +757,13 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
mut else_stmts := []ast.Stmt mut else_stmts := []ast.Stmt
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
p.check(.key_else) p.check(.key_else)
if p.tok.kind == .key_if {
p.if_expr()
}
else {
else_stmts = p.parse_block() else_stmts = p.parse_block()
} }
}
mut ti := table.void_type mut ti := table.void_type
// mut left := ast.Expr{} // mut left := ast.Expr{}
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
@ -944,13 +971,18 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
// println('struct field $ti.name $field_name') // println('struct field $ti.name $field_name')
} }
p.check(.rcbr) p.check(.rcbr)
p.table.register_type(table.Type{ if name != 'string' {
ret := p.table.register_type(table.Type{
kind: .struct_ kind: .struct_
name: name name: name
info: table.Struct{ info: table.Struct{
fields: fields fields: fields
} }
}) })
if ret == -1 {
p.error('cannot register type `$name`, another type with this name exists')
}
}
return ast.StructDecl{ return ast.StructDecl{
name: name name: name
is_pub: is_pub is_pub: is_pub

View File

@ -12,6 +12,8 @@ pub mut:
// type_idxs Hashmap // type_idxs Hashmap
type_idxs map[string]int type_idxs map[string]int
local_vars []Var local_vars []Var
scope_level int
var_idx int
// fns Hashmap // fns Hashmap
fns map[string]Fn fns map[string]Fn
consts map[string]Var consts map[string]Var
@ -29,9 +31,11 @@ pub:
pub struct Var { pub struct Var {
pub: pub:
name string name string
idx int
is_mut bool is_mut bool
is_const bool is_const bool
is_global bool is_global bool
scope_level int
mut: mut:
typ Type typ Type
} }
@ -52,32 +56,21 @@ pub fn (t &Table) find_var_idx(name string) int {
} }
pub fn (t &Table) find_var(name string) ?Var { pub fn (t &Table) find_var(name string) ?Var {
for i in 0 .. t.var_idx {
if t.local_vars[i].name == name {
return t.local_vars[i]
}
}
/* /*
for i in 0 .. p.var_idx {
if p.local_vars[i].name == name {
return p.local_vars[i]
}
}
*/
// println(t.names) // println(t.names)
for var in t.local_vars { for var in t.local_vars {
if var.name == name { if var.name == name {
return var return var
} }
} }
return none */
}
pub fn (t mut Table) clear_vars() { return none
// shared a := [1, 2, 3]
// p.var_idx = 0
if t.local_vars.len > 0 {
// if p.pref.autofree {
// p.local_vars.free()
// }
t.local_vars = []
}
} }
pub fn (t mut Table) register_const(v Var) { pub fn (t mut Table) register_const(v Var) {
@ -99,27 +92,76 @@ pub fn (t mut Table) register_global(name string, typ Type) {
pub fn (t mut Table) register_var(v Var) { pub fn (t mut Table) register_var(v Var) {
println('register_var: $v.name - $v.typ.name') println('register_var: $v.name - $v.typ.name')
t.local_vars << v
/*
mut new_var := { mut new_var := {
v | v |
idx:p.var_idx, idx:t.var_idx,
scope_level:p.cur_fn.scope_level scope_level:t.scope_level
} }
// t.local_vars << v
/*
if v.line_nr == 0 { if v.line_nr == 0 {
new_var.token_idx = p.cur_tok_index() new_var.token_idx = p.cur_tok_index()
new_var.line_nr = p.cur_tok().line_nr new_var.line_nr = p.cur_tok().line_nr
} }
*/
// Expand the array // Expand the array
if p.var_idx >= p.local_vars.len { if t.var_idx >= t.local_vars.len {
p.local_vars << new_var t.local_vars << new_var
} }
else { else {
p.local_vars[p.var_idx] = new_var t.local_vars[t.var_idx] = new_var
}
t.var_idx++
}
pub fn (t mut Table) open_scope() {
t.scope_level++
}
pub fn (t mut Table) close_scope() {
// println('close_scope level=$f.scope_level var_idx=$f.var_idx')
// Move back `var_idx` (pointer to the end of the array) till we reach
// the previous scope level. This effectivly deletes (closes) current
// scope.
mut i := t.var_idx - 1
for ; i >= 0; i-- {
var := t.local_vars[i]
/*
if p.pref.autofree && (v.is_alloc || (v.is_arg && v.typ == 'string')) {
// && !p.pref.is_test {
p.free_var(v)
} }
p.var_idx++
*/ */
// if p.fileis('mem.v') {
// println(v.name + ' $v.is_arg scope=$v.scope_level cur=$p.cur_fn.scope_level')}
if var.scope_level != t.scope_level {
// && !v.is_arg {
break
}
}
/*
if p.cur_fn.defer_text.last() != '' {
p.genln(p.cur_fn.defer_text.last())
// p.cur_fn.defer_text[f] = ''
}
*/
t.scope_level--
// p.cur_fn.defer_text = p.cur_fn.defer_text[..p.cur_fn.scope_level + 1]
t.var_idx = i + 1
// println('close_scope new var_idx=$f.var_idx\n')
}
pub fn (p mut Table) clear_vars() {
// shared a := [1, 2, 3]
p.var_idx = 0
if p.local_vars.len > 0 {
// ///if p.pref.autofree {
// p.local_vars.free()
// ///}
p.local_vars = []
}
} }
pub fn (t &Table) find_fn(name string) ?Fn { pub fn (t &Table) find_fn(name string) ?Fn {
@ -240,7 +282,7 @@ pub fn (t mut Table) register_type(typ Type) int {
if ex_type.kind == typ.kind { if ex_type.kind == typ.kind {
return existing_idx return existing_idx
} }
panic('cannot register type `$typ.name`, another type with this name exists') return -1
} }
} }
} }