v2: maps, <<, >>, method calls

pull/3647/head
Alexander Medvednikov 2020-02-04 12:50:58 +01:00
parent 21b54723e4
commit 9b60a50d07
8 changed files with 62 additions and 40 deletions

View File

@ -155,14 +155,17 @@ pub fn (n int) hex() string {
pub fn (n i64) hex() string { pub fn (n i64) hex() string {
len := if n >= i64(0) { n.str().len + 3 } else { 19 } len := if n >= i64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len) hex := malloc(len)
count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n) // QTODO
//count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
count := C.sprintf('%x', n)
return tos(hex, count) return tos(hex, count)
} }
pub fn (n u64) hex() string { 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)
return tos(hex, count) return tos(hex, count)
} }

View File

@ -6,13 +6,13 @@ module builtin
import strings import strings
// B-trees are balanced search trees with all leaves at // B-trees are balanced search trees with all leaves at
// the same level. B-trees are generally faster than // the same level. B-trees are generally faster than
// binary search trees due to the better locality of // binary search trees due to the better locality of
// reference, since multiple keys are stored in one node. // reference, since multiple keys are stored in one node.
// The number for `degree` has been picked through vigor- // The number for `degree` has been picked through vigor-
// ous benchmarking but can be changed to any number > 1. // ous benchmarking but can be changed to any number > 1.
// `degree` determines the size of each node. // `degree` determines the size of each node.
const ( const (
@ -32,7 +32,7 @@ pub mut:
struct mapnode { struct mapnode {
mut: mut:
keys [11]string // TODO: Should use `max_size` keys [11]string // TODO: Should use `max_size`
values [11]voidptr // TODO: Should use `max_size` values [11]voidptr // TODO: Should use `max_size`
children &voidptr children &voidptr
size int size int
@ -65,7 +65,7 @@ fn new_node() &mapnode {
} }
// This implementation does proactive insertion, meaning // This implementation does proactive insertion, meaning
// that splits are done top-down and not bottom-up. // that splits are done top-down and not bottom-up.
fn (m mut map) set(key string, value voidptr) { fn (m mut map) set(key string, value voidptr) {
mut node := m.root mut node := m.root
mut child_index := 0 mut child_index := 0
@ -179,7 +179,7 @@ fn (m map) exists(key string) bool {
return false return false
} }
fn (n mapnode) find_key(k string) int { fn (n mapnode) find_key(k string) int {
mut idx := 0 mut idx := 0
for idx < n.size && n.keys[idx] < k { for idx < n.size && n.keys[idx] < k {
idx++ idx++
@ -263,23 +263,23 @@ fn (n mut mapnode) borrow_from_prev(idx int) {
mut child := &mapnode(n.children[idx]) mut child := &mapnode(n.children[idx])
mut sibling := &mapnode(n.children[idx - 1]) mut sibling := &mapnode(n.children[idx - 1])
for i := child.size - 1; i >= 0; i-- { for i := child.size - 1; i >= 0; i-- {
child.keys[i + 1] = child.keys[i] child.keys[i + 1] = child.keys[i]
child.values[i + 1] = child.values[i] child.values[i + 1] = child.values[i]
} }
if !isnil(child.children) { if !isnil(child.children) {
for i := child.size; i >= 0; i-- { for i := child.size; i >= 0; i-- {
child.children[i + 1] = child.children[i] child.children[i + 1] = child.children[i]
} }
} }
child.keys[0] = n.keys[idx - 1] child.keys[0] = n.keys[idx - 1]
child.values[0] = n.values[idx - 1] child.values[0] = n.values[idx - 1]
if !isnil(child.children) { if !isnil(child.children) {
child.children[0] = sibling.children[sibling.size] child.children[0] = sibling.children[sibling.size]
} }
n.keys[idx - 1] = sibling.keys[sibling.size - 1] n.keys[idx - 1] = sibling.keys[sibling.size - 1]
n.values[idx - 1] = sibling.values[sibling.size - 1] n.values[idx - 1] = sibling.values[sibling.size - 1]
child.size++ child.size++
sibling.size-- sibling.size--
} }
fn (n mut mapnode) borrow_from_next(idx int) { fn (n mut mapnode) borrow_from_next(idx int) {
@ -340,7 +340,7 @@ pub fn (m mut map) delete(key string) {
if removed { if removed {
m.size-- m.size--
} }
if m.root.size == 0 { if m.root.size == 0 {
// tmp := t.root // tmp := t.root
if isnil(m.root.children) { if isnil(m.root.children) {
@ -353,7 +353,7 @@ pub fn (m mut map) delete(key string) {
} }
// Insert all keys of the subtree into array `keys` // Insert all keys of the subtree into array `keys`
// starting at `at`. Keys are inserted in order. // starting at `at`. Keys are inserted in order.
fn (n mapnode) subkeys(keys mut []string, at int) int { fn (n mapnode) subkeys(keys mut []string, at int) int {
mut position := at mut position := at
if !isnil(n.children) { if !isnil(n.children) {

View File

@ -12,16 +12,8 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
tok := p.tok tok := p.tok
fn_name := p.check_name() fn_name := p.check_name()
p.check(.lpar) p.check(.lpar)
mut args := []ast.Expr
// mut return_ti := types.void_ti // mut return_ti := types.void_ti
for p.tok.kind != .rpar { args := p.call_args()
e,_ := p.expr(0)
args << e
if p.tok.kind != .rpar {
p.check(.comma)
}
}
p.check(.rpar)
node := ast.CallExpr{ node := ast.CallExpr{
name: fn_name name: fn_name
args: args args: args
@ -39,6 +31,9 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
pub fn (p mut Parser) call_args() []ast.Expr { pub fn (p mut Parser) call_args() []ast.Expr {
mut args := []ast.Expr mut args := []ast.Expr
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
if p.tok.kind == .key_mut {
p.check(.key_mut)
}
e,_ := p.expr(0) e,_ := p.expr(0)
args << e args << e
if p.tok.kind != .rpar { if p.tok.kind != .rpar {
@ -97,7 +92,9 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
mut args := []table.Var mut args := []table.Var
mut ast_args := []ast.Arg mut ast_args := []ast.Arg
// `int, int, string` (no names, just types) // `int, int, string` (no names, just types)
types_only := p.tok.kind == .amp || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || p.peek_tok.kind == .rpar types_only := p.tok.kind in [.amp] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
//
p.peek_tok.kind == .rpar
if types_only { if types_only {
p.warn('types only') p.warn('types only')
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
@ -115,6 +112,9 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.check(.comma) p.check(.comma)
arg_names << p.check_name() arg_names << p.check_name()
} }
if p.tok.kind == .key_mut {
p.check(.key_mut)
}
ti := p.parse_type() ti := p.parse_type()
for arg_name in arg_names { for arg_name in arg_names {
arg := table.Var{ arg := table.Var{
@ -139,7 +139,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.check(.rpar) p.check(.rpar)
// Return type // Return type
mut typ := table.void_type mut typ := table.void_type
if p.tok.kind in [.name, .lpar, .amp] { if p.tok.kind in [.name, .lpar, .amp, .lsbr] {
typ = p.parse_type() typ = p.parse_type()
p.return_type = typ p.return_type = typ
} }

View File

@ -11,8 +11,9 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
// fixed array // fixed array
if p.tok.kind == .number { if p.tok.kind == .number {
size := p.tok.lit.int() size := p.tok.lit.int()
p.check(.rsbr)
elem_ti := p.parse_type() elem_ti := p.parse_type()
p.check(.rsbr)
p.check_name()
idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1) idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1)
return table.new_type(.array_fixed, name, idx, nr_muls) return table.new_type(.array_fixed, name, idx, nr_muls)
} }
@ -29,7 +30,10 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
return table.new_type(.array, name, idx, nr_muls) return table.new_type(.array, name, idx, nr_muls)
} }
pub fn (p mut Parser) parse_map_ti(nr_muls int) table.Type { pub fn (p mut Parser) parse_map_type(nr_muls int) table.Type {
if p.tok.kind != .lsbr {
return table.map_type
}
p.next() p.next()
p.check(.lsbr) p.check(.lsbr)
key_ti := p.parse_type() key_ti := p.parse_type()
@ -109,9 +113,8 @@ pub fn (p mut Parser) parse_type() table.Type {
p.next() p.next()
} }
match name { match name {
// map
'map' { 'map' {
return p.parse_map_ti(nr_muls) return p.parse_map_type(nr_muls)
} }
'voidptr' { 'voidptr' {
return table.new_type(.voidptr, 'voidptr', table.voidptr_type_idx, nr_muls) return table.new_type(.voidptr, 'voidptr', table.voidptr_type_idx, nr_muls)

View File

@ -376,7 +376,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
typ = ti2 typ = ti2
} }
// struct init // struct init
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string']) { else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string', 'mapnode', 'map']) {
typ = p.parse_type() typ = p.parse_type()
// p.warn('struct init typ=$typ.name') // p.warn('struct init typ=$typ.name')
p.check(.lcbr) p.check(.lcbr)
@ -919,9 +919,17 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
for p.tok.kind != .rcbr { for p.tok.kind != .rcbr {
if p.tok.kind == .key_pub { if p.tok.kind == .key_pub {
p.check(.key_pub) p.check(.key_pub)
if p.tok.kind == .key_mut {
p.check(.key_mut)
}
p.check(.colon)
}
else if p.tok.kind == .key_mut {
p.check(.key_mut)
p.check(.colon) p.check(.colon)
} }
field_name := p.check_name() field_name := p.check_name()
// p.warn('field $field_name')
ti := p.parse_type() ti := p.parse_type()
ast_fields << ast.Field{ ast_fields << ast.Field{
name: field_name name: field_name

View File

@ -541,7 +541,7 @@ pub fn (s mut Scanner) scan() token.Token {
return s.scan_res(.righ_shift_assign, '') return s.scan_res(.righ_shift_assign, '')
} }
s.pos++ s.pos++
return s.scan_res(.righ_shift, '') return s.scan_res(.right_shift, '')
} }
else { else {
return s.scan_res(.gt, '') return s.scan_res(.gt, '')

View File

@ -35,6 +35,7 @@ pub const (
char_type_idx = 15 char_type_idx = 15
byte_type_idx = 16 byte_type_idx = 16
bool_type_idx = 17 bool_type_idx = 17
map_type_idx = 18
) )
pub enum Kind { pub enum Kind {
@ -97,6 +98,11 @@ pub const (
name: 'byte' name: 'byte'
idx: byte_type_idx idx: byte_type_idx
} }
map_type = Type{
kind: .map
name: 'map'
idx: map_type_idx
}
) )
/* /*
pub fn (t Type) str() string { pub fn (t Type) str() string {

View File

@ -42,7 +42,7 @@ pub enum Kind {
dollar dollar
str_dollar str_dollar
left_shift left_shift
righ_shift right_shift
// at // @ // at // @
assign // = assign // =
decl_assign // := decl_assign // :=
@ -199,7 +199,7 @@ fn build_token_str() []string {
s[Kind.le] = '<=' s[Kind.le] = '<='
s[Kind.question] = '?' s[Kind.question] = '?'
s[Kind.left_shift] = '<<' s[Kind.left_shift] = '<<'
s[Kind.righ_shift] = '>>' s[Kind.right_shift] = '>>'
s[Kind.line_comment] = '// line comment' s[Kind.line_comment] = '// line comment'
s[Kind.mline_comment] = '/* mline comment */' s[Kind.mline_comment] = '/* mline comment */'
s[Kind.nl] = 'NLL' s[Kind.nl] = 'NLL'
@ -372,7 +372,7 @@ pub fn (tok Token) precedence() int {
return 7 return 7
} }
// `*` | `/` | `%` | `<<` | `>>` | `&` // `*` | `/` | `%` | `<<` | `>>` | `&`
.mul, .div, .mod, .left_shift, .righ_shift, .amp { .mul, .div, .mod, .left_shift, .right_shift, .amp {
return 6 return 6
} }
// `+` | `-` | `|` | `^` // `+` | `-` | `|` | `^`
@ -459,5 +459,7 @@ pub fn (tok Kind) is_relational() bool {
} }
pub fn (kind Kind) is_infix() bool { pub fn (kind Kind) is_infix() bool {
return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .ge, .le, .logical_or, .and, .dot, .pipe, .left_shift] return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .ge, .le, .logical_or,
//
.and, .dot, .pipe, .left_shift, .right_shift]
} }