register methods (wip)

pull/3370/head
Alexander Medvednikov 2020-01-08 10:19:12 +01:00
parent 3425934c39
commit 3c0fca9258
9 changed files with 294 additions and 229 deletions

View File

@ -166,6 +166,7 @@ pub fn (a array) last() voidptr {
return a.data + (a.len - 1) * a.element_size
}
/*
// array.left returns a new array using the same buffer as the given array
// with the first `n` elements of the given array.
fn (a array) left(n int) array {
@ -191,12 +192,7 @@ fn (a array) right(n int) array {
}
return a.slice(n, a.len)
}
// used internally for [2..4]
fn (a array) slice2(start, _end int, end_max bool) array {
end := if end_max { a.len } else { _end }
return a.slice(start, end)
}
*/
// array.slice returns an array using the same buffer as original array
// but starting from the `start` element and ending with the element before
@ -223,6 +219,29 @@ fn (a array) slice(start, _end int) array {
return res
}
// used internally for [2..4]
fn (a array) slice2(start, _end int, end_max bool) array {
end := if end_max { a.len } else { _end }
return a.slice(start, end)
}
// array.clone returns an independent copy of a given array
pub fn (a array) clone() array {
mut size := a.cap * a.element_size
if size == 0 {
size++
}
arr := array{
len: a.len
cap: a.cap
element_size: a.element_size
data: calloc(size)
}
C.memcpy(arr.data, a.data, a.cap * a.element_size)
return arr
}
fn (a array) slice_clone(start, _end int) array {
mut end := _end
if start > end {
@ -282,21 +301,6 @@ pub fn (a array) reverse() array {
return arr
}
// array.clone returns an independent copy of a given array
pub fn (a array) clone() array {
mut size := a.cap * a.element_size
if size == 0 {
size++
}
arr := array{
len: a.len
cap: a.cap
element_size: a.element_size
data: calloc(size)
}
C.memcpy(arr.data, a.data, a.cap * a.element_size)
return arr
}
// pub fn (a []int) free() {
[unsafe_fn]
@ -364,7 +368,7 @@ pub fn (b []byte) hex() string {
pub fn copy(dst, src []byte) int {
if dst.len > 0 && src.len > 0 {
min := if dst.len < src.len { dst.len } else { src.len }
C.memcpy(dst.data, src.left(min).data, dst.element_size * min)
C.memcpy(dst.data, src[min..].data, dst.element_size * min)
return min
}
return 0

View File

@ -222,11 +222,8 @@ fn test_repeat() {
fn test_right() {
a := [1, 2, 3, 4]
b := a.right(1)
c := a[1..a.len]
d := a[1..]
assert b[0] == 2
assert b[1] == 3
assert c[0] == 2
assert c[1] == 3
assert d[0] == 2
@ -252,18 +249,13 @@ fn test_right_with_n_bigger_than_array_size() {
fn test_left() {
a := [1, 2, 3]
b := a.left(2)
c := a[0..2]
d := a[..2]
e := a.left(4)
assert b[0] == 1
assert b[1] == 2
assert c[0] == 1
assert c[1] == 2
assert d[0] == 1
assert d[1] == 2
assert e[0] == 1
assert e[2] == 3
assert e.len == 3
}

View File

@ -149,6 +149,7 @@ $c_common_macros
byte g_str_buf[1024];
int load_so(byteptr);
void reload_so();
'
js_headers = '

View File

@ -77,6 +77,18 @@ fn (p mut Parser) bool_expression() string {
}
p.cgen.set_placeholder(start_ph, '*($cast_typ*)')
p.gen('.obj')
// Make sure the sum type can be cast, otherwise throw a runtime error
/*
sum_type:= p.cgen.cur_line.all_after('*) (').replace('.obj', '.typ')
n := cast_typ.all_after('__')
p.cgen.insert_before('if (($sum_type != SumType_$n) {
puts("runtime error: $p.file_name:$p.scanner.line_nr cannot cast sum type `$typ` to `$n`");
exit(1);
}
')
*/
} else {
p.cgen.set_placeholder(start_ph, '($cast_typ)(')
p.gen(')')

View File

@ -137,7 +137,17 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
ti = p.parse_ti()
p.return_ti = ti
}
if !is_method {
if is_method {
ok := p.table.register_method(rec_ti, table.Fn{
name: name
args: args
return_ti: ti
})
if !ok {
p.error('expected Struct')
}
}
else {
p.table.register_fn(table.Fn{
name: name
args: args

View File

@ -423,19 +423,12 @@ fn (p mut Parser) index_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
fn (p mut Parser) dot_expr(left ast.Expr, ti types.TypeIdent) (ast.Expr,types.TypeIdent) {
p.next()
field_name := p.check_name()
typ := p.table.types[ti.idx] as types.Struct
mut ok := false
for field in typ.fields {
if field.name == field_name {
ok = true
break
}
}
if !ok {
p.error('type `$typ.name` has no field or method `$field_name`')
}
struc := p.table.types[ti.idx] as types.Struct
// Method call
if p.tok.kind == .lpar {
if !p.table.struct_has_method(struc, field_name) {
p.error('type `$struc.name` has no method `$field_name`')
}
p.next()
args := p.call_args()
println('method call $field_name')
@ -447,6 +440,9 @@ fn (p mut Parser) dot_expr(left ast.Expr, ti types.TypeIdent) (ast.Expr,types.Ty
}
return node,types.int_ti
}
if !p.table.struct_has_field(struc, field_name) {
p.error('type `$struc.name` has no field `$field_name`')
}
/*
// p.next()
field := p.check_name()
@ -660,7 +656,7 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
p.check(.comma)
}
}
type_idx, type_name := p.table.find_or_register_array(val_ti, 1)
type_idx,type_name := p.table.find_or_register_array(val_ti, 1)
array_ti := types.new_ti(.array, type_name, type_idx, 0)
mut node := ast.Expr{}
node = ast.ArrayInit{

View File

@ -28,9 +28,9 @@ pub:
pub struct Fn {
pub:
name string
args []Var
return_ti types.TypeIdent
name string
args []Var
return_ti types.TypeIdent
}
pub fn new_table() &Table {
@ -116,8 +116,234 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
t.fns[new_fn.name] = new_fn
}
pub fn (t mut Table) register_method(ti types.TypeIdent, new_fn Fn) bool {
println('register method `$new_fn.name` tiname=$ti.name ')
match t.types[ti.idx] {
types.Struct {
println('got struct')
}
else {
return false
}
}
mut struc := t.types[ti.idx] as types.Struct
if struc.methods.len == 0 {
struc.methods = make(0, 0, sizeof(types.Field))
}
println('register method `$new_fn.name` struct=$struc.name ')
struc.methods << types.Field{
name: new_fn.name
}
t.types[ti.idx] = struc
return true
}
pub fn (t mut Table) new_tmp_var() string {
t.tmp_cnt++
return 'tmp$t.tmp_cnt'
}
pub fn (t &Table) struct_has_field(s &types.Struct, name string) bool {
println('struct_has_field($s.name, $name) s.idx=$s.idx types.len=$t.types.len s.parent_idx=$s.parent_idx')
// for typ in t.types {
// println('$typ.idx $typ.name')
// }
for field in s.fields {
if field.name == name {
return true
}
}
if s.parent_idx != 0 {
parent := t.types[s.parent_idx] as types.Struct
println('got parent $parent.name')
for field in parent.fields {
if field.name == name {
return true
}
}
}
return false
}
pub fn (t &Table) struct_has_method(s &types.Struct, name string) bool {
for field in s.methods {
if field.name == name {
return true
}
}
return false
}
[inline]
pub fn (t &Table) find_type_idx(name string) int {
return t.type_idxs[name]
}
[inline]
pub fn (t &Table) find_type(name string) ?types.Type {
idx := t.type_idxs[name]
if idx > 0 {
return t.types[idx]
}
return none
}
pub fn (t mut Table) register_struct(typ types.Struct) int {
println('register_struct($typ.name)')
// existing
existing_idx := t.type_idxs[typ.name]
if existing_idx > 0 {
ex_type := t.types[existing_idx]
match ex_type {
types.Placeholder {
// override placeholder
println('overriding type placeholder `$it.name` with struct')
mut struct_type := types.Type{}
struct_type = {
typ |
idx:existing_idx
}
t.types[existing_idx] = struct_type
return existing_idx
}
types.Struct {
return existing_idx
}
else {
panic('cannot register type `$typ.name`, another type with this name exists')
}
}
}
// register
println('registering: $typ.name')
idx := t.types.len
t.type_idxs[typ.name] = idx
mut struct_type := types.Type{}
struct_type = {
typ |
idx:idx,
parent_idx:0,
}
t.types << struct_type
return idx
}
pub fn (t mut Table) find_or_register_map(key_ti &types.TypeIdent, value_ti &types.TypeIdent) (int,string) {
name := 'map_${key_ti.name}_${value_ti.name}'
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut map_type := types.Type{}
map_type = types.Map{
name: name
key_type_idx: key_ti.idx
value_type_idx: value_ti.idx
}
t.type_idxs[name] = idx
t.types << map_type
return idx,name
}
pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims int) (int,string) {
name := 'array_${elem_ti.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut array_type := types.Type{}
array_type = types.Array{
idx: idx
name: name
elem_type_idx: elem_ti.idx
elem_is_ptr: elem_ti.is_ptr()
nr_dims: nr_dims
}
t.type_idxs[name] = idx
t.types << array_type
return idx,name
}
pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size int, nr_dims int) (int,string) {
name := 'array_fixed_${elem_ti.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut array_fixed_type := types.Type{}
array_fixed_type = types.ArrayFixed{
idx: idx
name: name
elem_type_idx: elem_ti.idx
elem_is_ptr: elem_ti.is_ptr()
size: size
nr_dims: nr_dims
}
t.type_idxs[name] = idx
t.types << array_fixed_type
return idx,name
}
pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (int,string) {
mut name := 'multi_return'
for mr_ti in mr_tis {
name += '_$mr_ti.name'
}
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut mr_type := types.Type{}
mr_type = types.MultiReturn{
idx: idx
name: name
tis: mr_tis
}
t.type_idxs[name] = idx
t.types << mr_type
return idx,name
}
pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (int,string) {
name := 'variadic_$variadic_ti.name'
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut variadic_type := types.Type{}
variadic_type = types.Variadic{
idx: idx
ti: variadic_ti
}
t.type_idxs[name] = idx
t.types << variadic_type
return idx,name
}
pub fn (t mut Table) add_placeholder_type(name string) int {
idx := t.types.len
t.type_idxs[name] = t.types.len
mut pt := types.Type{}
pt = types.Placeholder{
idx: idx
name: name
}
println('added placeholder: $name - $idx ')
t.types << pt
return idx
}

View File

@ -1,178 +0,0 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module table
import v.types
[inline]
pub fn (t &Table) find_type_idx(name string) int {
return t.type_idxs[name]
}
[inline]
pub fn (t &Table) find_type(name string) ?types.Type {
idx := t.type_idxs[name]
if idx > 0 {
return t.types[idx]
}
return none
}
pub fn (t mut Table) register_struct(typ types.Struct) int {
// existing
existing_idx := t.type_idxs[typ.name]
if existing_idx > 0 {
ex_type := t.types[existing_idx]
match ex_type {
types.Placeholder {
// override placeholder
println('overriding type placeholder `$it.name` with struct')
mut struct_type := types.Type{}
struct_type = {
typ |
idx:existing_idx
}
t.types[existing_idx] = struct_type
return existing_idx
}
types.Struct {
return existing_idx
}
else {
panic('cannot register type `$typ.name`, another type with this name exists')
}
}
}
// register
println('registering: $typ.name')
idx := t.types.len
t.type_idxs[typ.name] = idx
mut struct_type := types.Type{}
struct_type = {
typ |
idx:idx
}
t.types << struct_type
return idx
}
pub fn (t mut Table) find_or_register_map(key_ti &types.TypeIdent, value_ti &types.TypeIdent) (int,string) {
name := 'map_${key_ti.name}_${value_ti.name}'
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut map_type := types.Type{}
map_type = types.Map{
name: name
key_type_idx: key_ti.idx
value_type_idx: value_ti.idx
}
t.type_idxs[name] = idx
t.types << map_type
return idx,name
}
pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims int) (int,string) {
name := 'array_${elem_ti.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut array_type := types.Type{}
array_type = types.Array{
idx: idx
name: name
elem_type_idx: elem_ti.idx
elem_is_ptr: elem_ti.is_ptr()
nr_dims: nr_dims
}
t.type_idxs[name] = idx
t.types << array_type
return idx,name
}
pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size int, nr_dims int) (int,string) {
name := 'array_fixed_${elem_ti.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' }
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut array_fixed_type := types.Type{}
array_fixed_type = types.ArrayFixed{
idx: idx
name: name
elem_type_idx: elem_ti.idx
elem_is_ptr: elem_ti.is_ptr()
size: size
nr_dims: nr_dims
}
t.type_idxs[name] = idx
t.types << array_fixed_type
return idx,name
}
pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (int,string) {
mut name := 'multi_return'
for mr_ti in mr_tis {
name += '_$mr_ti.name'
}
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut mr_type := types.Type{}
mr_type = types.MultiReturn{
idx: idx
name: name
tis: mr_tis
}
t.type_idxs[name] = idx
t.types << mr_type
return idx,name
}
pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (int,string) {
name := 'variadic_$variadic_ti.name'
// existing
existing_idx := t.type_idxs[name]
if existing_idx > 0 {
return existing_idx,name
}
// register
idx := t.types.len
mut variadic_type := types.Type{}
variadic_type = types.Variadic{
idx: idx
ti: variadic_ti
}
t.type_idxs[name] = idx
t.types << variadic_type
return idx,name
}
pub fn (t mut Table) add_placeholder_type(name string) int {
idx := t.types.len
t.type_idxs[name] = t.types.len
mut pt := types.Type{}
pt = types.Placeholder{
idx: idx
name: name
}
println('added placeholder: $name - $idx ')
t.types << pt
return idx
}

View File

@ -56,7 +56,7 @@ pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent {
[inline]
pub fn new_builtin_ti(kind Kind, nr_muls int) TypeIdent {
return TypeIdent{
idx: -int(kind)-1
idx: -int(kind) - 1
kind: kind
name: kind.str()
nr_muls: nr_muls
@ -224,10 +224,12 @@ pub:
pub struct Struct {
pub:
idx int
name string
fields []Field
// methods
idx int
parent_idx int
name string
pub mut:
fields []Field
methods []Field // TODO Method
}
pub struct Field {