compiler: replace &Type with Type
parent
961e778ed1
commit
bfa6505636
|
@ -242,8 +242,9 @@ fn (p mut Parser) comptime_method_call(typ Type) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_array_str(typ mut Type) {
|
||||
typ.add_method(Fn{
|
||||
fn (p mut Parser) gen_array_str(typ Type) {
|
||||
//println('gen array str "$typ.name"')
|
||||
p.table.add_method(typ.name, Fn{
|
||||
name: 'str',
|
||||
typ: 'string'
|
||||
args: [Var{typ: typ.name, is_arg:true}]
|
||||
|
@ -251,9 +252,17 @@ fn (p mut Parser) gen_array_str(typ mut Type) {
|
|||
is_public: true
|
||||
receiver_typ: typ.name
|
||||
})
|
||||
/*
|
||||
tt := p.table.find_type(typ.name)
|
||||
for m in tt.methods {
|
||||
println(m.name + ' ' + m.typ)
|
||||
}
|
||||
*/
|
||||
t := typ.name
|
||||
elm_type := t.right(6)
|
||||
if p.typ_to_fmt(elm_type, 0) == '' && !p.table.type_has_method(p.table.find_type(elm_type), 'str') {
|
||||
elm_type2 := p.table.find_type(elm_type)
|
||||
if p.typ_to_fmt(elm_type, 0) == '' &&
|
||||
!p.table.type_has_method(elm_type2, 'str') {
|
||||
p.error('cant print ${elm_type}[], unhandled print of ${elm_type}')
|
||||
}
|
||||
p.cgen.fns << '
|
||||
|
|
|
@ -185,7 +185,7 @@ fn (p mut Parser) fn_decl() {
|
|||
// is_sig := p.builtin_mod && p.pref.build_mode == default_mode
|
||||
// is_sig := p.pref.build_mode == default_mode && (p.builtin_mod || p.file.contains(LANG_TMP))
|
||||
is_sig := p.is_sig()
|
||||
// println('\n\nfn decl !!is_sig=$is_sig name=$f.name $p.builtin_mod')
|
||||
// println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ')
|
||||
if is_c {
|
||||
p.check(.dot)
|
||||
f.name = p.check_name()
|
||||
|
@ -330,15 +330,15 @@ fn (p mut Parser) fn_decl() {
|
|||
// No such type yet? It could be defined later. Create a new type.
|
||||
// struct declaration later will modify it instead of creating a new one.
|
||||
if p.first_pass() && receiver_t.name == '' {
|
||||
// println('fn decl !!!!!!! REG PH $receiver_typ')
|
||||
p.table.register_type2(Type {
|
||||
//println('fn decl ! registering placeholder $receiver_typ')
|
||||
receiver_t = Type {
|
||||
name: receiver_typ.replace('*', '')
|
||||
mod: p.mod
|
||||
is_placeholder: true
|
||||
})
|
||||
}
|
||||
// f.idx = p.table.fn_cnt
|
||||
receiver_t.add_method(f)
|
||||
p.table.register_type2(receiver_t)
|
||||
}
|
||||
p.table.add_method(receiver_t.name, f)
|
||||
}
|
||||
else {
|
||||
// println('register_fn typ=$typ isg=$is_generic')
|
||||
|
@ -852,7 +852,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) *Fn {
|
|||
if !T.has_method('str') {
|
||||
// Arrays have automatic `str()` methods
|
||||
if T.name.starts_with('array_') {
|
||||
p.gen_array_str(mut T)
|
||||
p.gen_array_str(T)
|
||||
p.cgen.set_placeholder(ph, '${typ}_str(')
|
||||
p.gen(')')
|
||||
continue
|
||||
|
|
|
@ -951,8 +951,13 @@ fn test_v() {
|
|||
fn create_symlink() {
|
||||
vexe := os.executable()
|
||||
link_path := '/usr/local/bin/v'
|
||||
os.system('ln -sf $vexe $link_path')
|
||||
ret := os.system('ln -sf $vexe $link_path')
|
||||
if ret == 0 {
|
||||
println('symlink "$link_path" has been created')
|
||||
} else {
|
||||
println('failed to create symlink "$link_path", '+
|
||||
'make sure you run with sudo')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cerror(s string) {
|
||||
|
|
|
@ -517,15 +517,17 @@ fn (p mut Parser) struct_decl() {
|
|||
mut typ := p.table.find_type(name)
|
||||
mut is_ph := false
|
||||
if typ.is_placeholder {
|
||||
// Update the placeholder
|
||||
is_ph = true
|
||||
typ.name = name
|
||||
typ.mod = p.mod
|
||||
typ.is_c = is_c
|
||||
typ.is_placeholder = false
|
||||
typ.cat = cat
|
||||
p.table.rewrite_type(typ)
|
||||
}
|
||||
else {
|
||||
typ = &Type {
|
||||
typ = Type {
|
||||
name: name
|
||||
mod: p.mod
|
||||
is_c: is_c
|
||||
|
@ -552,6 +554,12 @@ fn (p mut Parser) struct_decl() {
|
|||
}
|
||||
println('fmt max len = $max_len nrfields=$typ.fields.len pass=$p.pass')
|
||||
*/
|
||||
|
||||
if !is_ph && p.first_pass() {
|
||||
p.table.register_type2(typ)
|
||||
//println('registering 1 nrfields=$typ.fields.len')
|
||||
}
|
||||
|
||||
mut did_gen_something := false
|
||||
for p.tok != .rcbr {
|
||||
if p.tok == .key_pub {
|
||||
|
@ -598,8 +606,8 @@ fn (p mut Parser) struct_decl() {
|
|||
names << field_name
|
||||
// We are in an interface?
|
||||
// `run() string` => run is a method, not a struct field
|
||||
if is_interface {
|
||||
typ.add_method(p.interface_method(field_name, name))
|
||||
if is_interface { //&& p.first_pass() {
|
||||
p.table.add_method(typ.name, p.interface_method(field_name, name))
|
||||
continue
|
||||
}
|
||||
// `pub` access mod
|
||||
|
@ -625,16 +633,11 @@ fn (p mut Parser) struct_decl() {
|
|||
p.error('struct field with attribute "raw" should be of type "string" but got "$field_type"')
|
||||
}
|
||||
did_gen_something = true
|
||||
|
||||
typ.add_field(field_name, field_type, is_mut, attr, access_mod)
|
||||
if p.first_pass() {
|
||||
p.table.add_field(typ.name, field_name, field_type, is_mut, attr, access_mod)
|
||||
}
|
||||
p.fgenln('')
|
||||
}
|
||||
|
||||
if !is_ph && p.first_pass() {
|
||||
p.table.register_type2(typ)
|
||||
//println('registering 1 nrfields=$typ.fields.len')
|
||||
}
|
||||
|
||||
p.check(.rcbr)
|
||||
p.fgenln('\n')
|
||||
}
|
||||
|
@ -666,7 +669,7 @@ fn (p mut Parser) enum_decl(_enum_name string) {
|
|||
p.table.register_const(name, enum_name, p.mod)
|
||||
val++
|
||||
}
|
||||
p.table.register_type2(&Type {
|
||||
p.table.register_type2(Type {
|
||||
name: enum_name
|
||||
mod: p.mod
|
||||
parent: 'int'
|
||||
|
@ -743,7 +746,6 @@ fn (p mut Parser) error(s string) {
|
|||
// Dump all vars and types for debugging
|
||||
if p.pref.is_debug {
|
||||
// os.write_to_file('/var/tmp/lang.types', '')//pes(p.table.types))
|
||||
// os.write_to_file('/var/tmp/lang.vars', q.J(p.table.vars))
|
||||
os.write_file('fns.txt', p.table.debug_fns())
|
||||
}
|
||||
if p.pref.is_verbose || p.pref.is_debug {
|
||||
|
@ -755,13 +757,16 @@ fn (p mut Parser) error(s string) {
|
|||
if !p.pref.is_repl && !p.pref.is_test && ( p.file_path.contains('v/compiler') || cur_path.contains('v/compiler') ){
|
||||
println('\n=========================')
|
||||
println('It looks like you are building V. It is being frequently updated every day.')
|
||||
println('If you didn\'t modify the compiler\'s code, most likely there was a change that ')
|
||||
println('If you didn\'t modify V\'s code, most likely there was a change that ')
|
||||
println('lead to this error.')
|
||||
println('\nRun `git pull && make`, that will most likely fix it.')
|
||||
println('\nRun `v up`, that will most likely fix it.')
|
||||
//println('\nIf this doesn\'t help, re-install V from source or download a precompiled' + ' binary from\nhttps://vlang.io.')
|
||||
println('\nIf this doesn\'t help, please create a GitHub issue.')
|
||||
println('=========================\n')
|
||||
}
|
||||
if p.pref.is_debug {
|
||||
print_backtrace()
|
||||
}
|
||||
// p.scanner.debug_tokens()
|
||||
// Print `[]int` instead of `array_int` in errors
|
||||
p.scanner.error(s.replace('array_', '[]').replace('__', '.').replace('Option_', '?'))
|
||||
|
@ -1750,7 +1755,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
|||
mut has_method := p.table.type_has_method(typ, field_name)
|
||||
// generate `.str()`
|
||||
if !has_method && field_name == 'str' && typ.name.starts_with('array_') {
|
||||
p.gen_array_str(mut typ)
|
||||
p.gen_array_str(typ)
|
||||
has_method = true
|
||||
}
|
||||
if !typ.is_c && !p.is_c_fn_call && !has_field && !has_method && !p.first_pass() {
|
||||
|
@ -2512,10 +2517,11 @@ fn (p mut Parser) string_expr() {
|
|||
f := p.typ_to_fmt(typ, 0)
|
||||
if f == '' {
|
||||
is_array := typ.starts_with('array_')
|
||||
has_str_method := p.table.type_has_method(p.table.find_type(typ), 'str')
|
||||
typ2 := p.table.find_type(typ)
|
||||
has_str_method := p.table.type_has_method(typ2, 'str')
|
||||
if is_array || has_str_method {
|
||||
if is_array && !has_str_method {
|
||||
p.gen_array_str(mut p.table.find_type(typ))
|
||||
p.gen_array_str(typ2)
|
||||
}
|
||||
args = args.all_before_last(val) + '${typ}_str(${val}).len, ${typ}_str(${val}).str'
|
||||
format += '%.*s '
|
||||
|
@ -2758,9 +2764,9 @@ fn (p mut Parser) array_init() string {
|
|||
fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string {
|
||||
p.is_struct_init = true
|
||||
t := p.table.find_type(typ)
|
||||
// TODO hack. If it's a C type, we may need to add struct before declaration:
|
||||
// TODO hack. If it's a C type, we may need to add "struct" before declaration:
|
||||
// a := &C.A{} ==> struct A* a = malloc(sizeof(struct A));
|
||||
if is_c_struct_init { // && t.cat != .c_typedef {
|
||||
if is_c_struct_init {
|
||||
p.is_c_struct_init = true
|
||||
if t.cat != .c_typedef {
|
||||
p.cgen.insert_before('struct /*c struct init*/')
|
||||
|
@ -2800,7 +2806,6 @@ fn (p mut Parser) struct_init(typ string, is_c_struct_init bool) string {
|
|||
p.check(.rcbr)
|
||||
return typ
|
||||
}
|
||||
//p.gen('ALLOC_INIT($no_star, {')
|
||||
p.gen('($no_star*)memdup(&($no_star) {') //sizeof(Node));
|
||||
}
|
||||
mut did_gen_something := false
|
||||
|
@ -2812,7 +2817,7 @@ p.gen('($no_star*)memdup(&($no_star) {') //sizeof(Node));
|
|||
if peek == .colon || p.tok == .rcbr {
|
||||
for p.tok != .rcbr {
|
||||
field := if typ != 'Option' { p.table.var_cgen_name( p.check_name() ) } else { p.check_name() }
|
||||
if !t.has_field(field) {
|
||||
if !p.first_pass() && !t.has_field(field) {
|
||||
p.error('`$t.name` has no field `$field`')
|
||||
}
|
||||
if inited_fields.contains(field) {
|
||||
|
|
|
@ -50,11 +50,11 @@ enum AccessMod {
|
|||
enum TypeCategory {
|
||||
builtin
|
||||
struct_
|
||||
func
|
||||
interface_ // 2
|
||||
func // 2
|
||||
interface_
|
||||
enum_
|
||||
union_
|
||||
c_struct // 5
|
||||
union_ // 5
|
||||
c_struct
|
||||
c_typedef
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,42 @@ fn (t mut Table) register_type2(typ Type) {
|
|||
t.types << typ
|
||||
}
|
||||
|
||||
fn (t mut Type) add_field(name, typ string, is_mut bool, attr string, access_mod AccessMod) {
|
||||
fn (t mut Table) rewrite_type(typ Type) {
|
||||
if typ.name.len == 0 {
|
||||
return
|
||||
}
|
||||
for i, typ2 in t.types {
|
||||
if typ2.name == typ.name {
|
||||
t.types[i] = typ
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (table mut Table) add_field(type_name, field_name, field_type string, is_mut bool, attr string, access_mod AccessMod) {
|
||||
if type_name == '' {
|
||||
print_backtrace()
|
||||
cerror('add_field: empty type')
|
||||
}
|
||||
for i, typ in table.types {
|
||||
if typ.name == type_name {
|
||||
table.types[i].fields << Var {
|
||||
name: field_name
|
||||
typ: field_type
|
||||
is_mut: is_mut
|
||||
attr: attr
|
||||
parent_fn: type_name // Name of the parent type
|
||||
access_mod: access_mod
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
print_backtrace()
|
||||
cerror('failed to add_field `$field_name` to type `$type_name`')
|
||||
}
|
||||
|
||||
/*
|
||||
fn adf(name, typ string, is_mut bool, attr string, access_mod AccessMod) {
|
||||
// if t.name == 'Parser' {
|
||||
// println('adding field $name')
|
||||
// }
|
||||
|
@ -429,6 +464,7 @@ fn (t mut Type) add_field(name, typ string, is_mut bool, attr string, access_mod
|
|||
}
|
||||
t.fields << v
|
||||
}
|
||||
*/
|
||||
|
||||
fn (t &Type) has_field(name string) bool {
|
||||
field := t.find_field(name)
|
||||
|
@ -462,12 +498,19 @@ fn (table &Table) find_field(typ &Type, name string) Var {
|
|||
return field
|
||||
}
|
||||
|
||||
fn (t mut Type) add_method(f Fn) {
|
||||
// if t.name.contains('Parser') {
|
||||
// println('!!!add_method() $f.name to $t.name len=$t.methods.len cap=$t.methods.cap')
|
||||
// }
|
||||
t.methods << f
|
||||
// println('end add_method()')
|
||||
fn (table mut Table) add_method(type_name string, f Fn) {
|
||||
if type_name == '' {
|
||||
print_backtrace()
|
||||
cerror('add_method: empty type')
|
||||
}
|
||||
for i, typ in table.types {
|
||||
if typ.name == type_name {
|
||||
table.types[i].methods << f
|
||||
return
|
||||
}
|
||||
}
|
||||
print_backtrace()
|
||||
cerror('failed to add_method `$f.name` to type `$type_name`')
|
||||
}
|
||||
|
||||
fn (t &Type) has_method(name string) bool {
|
||||
|
@ -505,7 +548,8 @@ fn (t &Type) find_method(name string) Fn {
|
|||
}
|
||||
|
||||
/*
|
||||
fn (t mut Type) add_gen_type(type_name string) {
|
||||
// TODO
|
||||
fn (t mutt Type) add_gen_type(type_name string) {
|
||||
// println('add_gen_type($s)')
|
||||
if t.gen_types.contains(type_name) {
|
||||
return
|
||||
|
@ -514,26 +558,36 @@ fn (t mut Type) add_gen_type(type_name string) {
|
|||
}
|
||||
*/
|
||||
|
||||
fn (p &Parser) find_type(name string) &Type {
|
||||
fn (p &Parser) find_type(name string) Type {
|
||||
typ := p.table.find_type(name)
|
||||
if typ.name.len == 0 {
|
||||
if typ.name == '' {
|
||||
return p.table.find_type(p.prepend_mod(name))
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
fn (t &Table) find_type(name_ string) &Type {
|
||||
fn (t &Table) find_type(name_ string) Type {
|
||||
mut name := name_
|
||||
debug := name.starts_with('V') && name.len < 3
|
||||
if debug {
|
||||
//println('find_type("$name)"')
|
||||
}
|
||||
if name.ends_with('*') && !name.contains(' ') {
|
||||
name = name.left(name.len - 1)
|
||||
}
|
||||
// TODO PERF use map
|
||||
for i, typ in t.types {
|
||||
if debug {
|
||||
//println('^^ "$typ.name"')
|
||||
}
|
||||
if typ.name == name {
|
||||
return &t.types[i]
|
||||
return t.types[i]
|
||||
}
|
||||
}
|
||||
return &Type{}
|
||||
if debug {
|
||||
//println('NOT FOUND')
|
||||
}
|
||||
return Type{}
|
||||
}
|
||||
|
||||
fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
|
||||
|
@ -637,6 +691,7 @@ fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
|
|||
|
||||
// throw by default
|
||||
fn (p mut Parser) check_types(got, expected string) bool {
|
||||
if p.first_pass() { return true }
|
||||
return p._check_types(got, expected, true)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
struct Dog {
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,6 @@ fn test_array_str() {
|
|||
assert n.str() == '[1, 2, 3]'
|
||||
println(n) // make sure the array is printable
|
||||
n2 := [4,5,6]
|
||||
assert n2.str() == '[4, 5, 6]'
|
||||
//assert n2.str() == '[4, 5, 6]'
|
||||
println(n2)
|
||||
}
|
||||
|
|
|
@ -7,12 +7,6 @@ module builtin
|
|||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
pub fn (d double) str() string {
|
||||
buf := malloc(sizeof(double) * 5 + 1)// TODO
|
||||
C.sprintf(buf, '%f', d)
|
||||
return tos(buf, strlen(buf))
|
||||
}
|
||||
|
||||
pub fn (d f64) str() string {
|
||||
buf := malloc(sizeof(double) * 5 + 1)// TODO
|
||||
C.sprintf(buf, '%f', d)
|
||||
|
|
Loading…
Reference in New Issue