parser/cgen: interfaces (part 1)
parent
faed178cb1
commit
d7ee4755c2
|
@ -157,6 +157,7 @@ pub struct InterfaceDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
field_names []string
|
field_names []string
|
||||||
|
methods []FnDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructInitField {
|
pub struct StructInitField {
|
||||||
|
@ -541,7 +542,6 @@ pub:
|
||||||
name string
|
name string
|
||||||
is_pub bool
|
is_pub bool
|
||||||
fields []EnumField
|
fields []EnumField
|
||||||
// default_exprs []Expr
|
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,22 +739,46 @@ pub fn expr_is_call(expr Expr) bool {
|
||||||
|
|
||||||
fn (expr Expr) position() token.Position {
|
fn (expr Expr) position() token.Position {
|
||||||
// all uncommented have to be implemented
|
// all uncommented have to be implemented
|
||||||
match var expr {
|
match mut expr {
|
||||||
ArrayInit { return it.pos }
|
ArrayInit {
|
||||||
AsCast { return it.pos }
|
return it.pos
|
||||||
|
}
|
||||||
|
AsCast {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.Ident { }
|
// ast.Ident { }
|
||||||
AssignExpr { return it.pos }
|
AssignExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.CastExpr { }
|
// ast.CastExpr { }
|
||||||
Assoc { return it.pos }
|
Assoc {
|
||||||
BoolLiteral { return it.pos }
|
return it.pos
|
||||||
CallExpr { return it.pos }
|
}
|
||||||
CharLiteral { return it.pos }
|
BoolLiteral {
|
||||||
EnumVal { return it.pos }
|
return it.pos
|
||||||
FloatLiteral { return it.pos }
|
}
|
||||||
Ident { return it.pos }
|
CallExpr {
|
||||||
IfExpr { return it.pos }
|
return it.pos
|
||||||
|
}
|
||||||
|
CharLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
EnumVal {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
FloatLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
Ident {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
IfExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.IfGuardExpr { }
|
// ast.IfGuardExpr { }
|
||||||
IndexExpr { return it.pos }
|
IndexExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
InfixExpr {
|
InfixExpr {
|
||||||
left_pos := it.left.position()
|
left_pos := it.left.position()
|
||||||
right_pos := it.right.position()
|
right_pos := it.right.position()
|
||||||
|
@ -767,20 +791,40 @@ fn (expr Expr) position() token.Position {
|
||||||
len: right_pos.pos - left_pos.pos + right_pos.len
|
len: right_pos.pos - left_pos.pos + right_pos.len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IntegerLiteral { return it.pos }
|
IntegerLiteral {
|
||||||
MapInit { return it.pos }
|
return it.pos
|
||||||
MatchExpr { return it.pos }
|
}
|
||||||
PostfixExpr { return it.pos }
|
MapInit {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
MatchExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
|
PostfixExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.None { }
|
// ast.None { }
|
||||||
PrefixExpr { return it.pos }
|
PrefixExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.ParExpr { }
|
// ast.ParExpr { }
|
||||||
SelectorExpr { return it.pos }
|
SelectorExpr {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.SizeOf { }
|
// ast.SizeOf { }
|
||||||
StringLiteral { return it.pos }
|
StringLiteral {
|
||||||
StringInterLiteral { return it.pos }
|
return it.pos
|
||||||
|
}
|
||||||
|
StringInterLiteral {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.Type { }
|
// ast.Type { }
|
||||||
StructInit { return it.pos }
|
StructInit {
|
||||||
|
return it.pos
|
||||||
|
}
|
||||||
// ast.TypeOf { }
|
// ast.TypeOf { }
|
||||||
else { return token.Position{} }
|
else {
|
||||||
|
return token.Position{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,13 +471,13 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
||||||
//println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
//println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
|
||||||
c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
|
c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
|
||||||
}
|
}
|
||||||
no_args := method.args.len - 1
|
nr_args := if method.args.len == 0 { 0 } else {method.args.len - 1}
|
||||||
min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 }
|
min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 }
|
||||||
if call_expr.args.len < min_required_args {
|
if call_expr.args.len < min_required_args {
|
||||||
c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)',
|
c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)',
|
||||||
call_expr.pos)
|
call_expr.pos)
|
||||||
} else if !method.is_variadic && call_expr.args.len > no_args {
|
} else if !method.is_variadic && call_expr.args.len > nr_args {
|
||||||
c.error('too many arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $no_args)',
|
c.error('!too many arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $nr_args)',
|
||||||
call_expr.pos)
|
call_expr.pos)
|
||||||
return method.return_type
|
return method.return_type
|
||||||
}
|
}
|
||||||
|
@ -530,7 +530,7 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
||||||
return info.func.return_type
|
return info.func.return_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.error('unknown method: ${left_type_sym.name}.$method_name', call_expr.pos)
|
c.error('unknown method: `${left_type_sym.name}.$method_name`', call_expr.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/inout/unknown_method.v:7:12: error: unknown method: Test.sdd
|
vlib/v/checker/tests/inout/unknown_method.v:7:12: error: unknown method: `Test.sdd`
|
||||||
5| fn main() {
|
5| fn main() {
|
||||||
6| t := Test{}
|
6| t := Test{}
|
||||||
7| println(t.sdd())
|
7| println(t.sdd())
|
||||||
|
|
|
@ -333,6 +333,14 @@ fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
// Imports are handled after the file is formatted, to automatically add necessary modules
|
// Imports are handled after the file is formatted, to automatically add necessary modules
|
||||||
// f.imports(f.file.imports)
|
// f.imports(f.file.imports)
|
||||||
}
|
}
|
||||||
|
ast.InterfaceDecl {
|
||||||
|
f.writeln('interface $it.name {')
|
||||||
|
for method in it.methods {
|
||||||
|
f.write('\t')
|
||||||
|
f.writeln(method.str(f.table).after('fn '))
|
||||||
|
}
|
||||||
|
f.writeln('}\n')
|
||||||
|
}
|
||||||
ast.Module {
|
ast.Module {
|
||||||
f.mod(it)
|
f.mod(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,17 +151,11 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
g.finish()
|
g.finish()
|
||||||
return g.hashes() +
|
return g.hashes() + '\n// V typedefs:\n' + g.typedefs.str() + '\n// V typedefs2:\n' + g.typedefs2.str() +
|
||||||
'\n// V typedefs:\n' + g.typedefs.str() +
|
'\n// V cheaders:\n' + g.cheaders.str() + '\n// V includes:\n' + g.includes.str() + '\n// V definitions:\n' +
|
||||||
'\n// V typedefs2:\n' + g.typedefs2.str() +
|
g.definitions.str() + g.interface_table() + '\n// V gowrappers:\n' + g.gowrappers.str() + '\n// V stringliterals:\n' +
|
||||||
'\n// V cheaders:\n' + g.cheaders.str() +
|
g.stringliterals.str() + '\n// V auto str functions:\n' + g.auto_str_funcs.str() + '\n// V out\n' +
|
||||||
'\n// V includes:\n' + g.includes.str() +
|
g.out.str() + '\n// THE END.'
|
||||||
'\n// V definitions:\n' + g.definitions.str() +
|
|
||||||
'\n// V gowrappers:\n' + g.gowrappers.str() +
|
|
||||||
'\n// V stringliterals:\n' + g.stringliterals.str() +
|
|
||||||
'\n// V auto str functions:\n' + g.auto_str_funcs.str() +
|
|
||||||
'\n// V out\n' + g.out.str() +
|
|
||||||
'\n// THE END.'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (g Gen) hashes() string {
|
pub fn (g Gen) hashes() string {
|
||||||
|
@ -400,10 +394,10 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
match node {
|
match node {
|
||||||
ast.InterfaceDecl {
|
ast.InterfaceDecl {
|
||||||
g.writeln('//interface')
|
g.writeln('//interface')
|
||||||
g.writeln('struct $it.name {')
|
g.writeln('typedef struct {')
|
||||||
g.writeln('\tvoid* _object;')
|
g.writeln('\tvoid* _object;')
|
||||||
g.writeln('\tint _interface_idx;')
|
g.writeln('\tint _interface_idx;')
|
||||||
g.writeln('};')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
ast.AssertStmt {
|
ast.AssertStmt {
|
||||||
g.gen_assert_stmt(it)
|
g.gen_assert_stmt(it)
|
||||||
|
@ -458,11 +452,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
cur_enum_expr = expr_str
|
cur_enum_expr = expr_str
|
||||||
cur_enum_offset = 0
|
cur_enum_offset = 0
|
||||||
}
|
}
|
||||||
cur_value := if cur_enum_offset > 0 {
|
cur_value := if cur_enum_offset > 0 { '${cur_enum_expr}+${cur_enum_offset}' } else { cur_enum_expr }
|
||||||
'${cur_enum_expr}+${cur_enum_offset}'
|
|
||||||
} else {
|
|
||||||
cur_enum_expr
|
|
||||||
}
|
|
||||||
g.typedefs.writeln(', // ${cur_value}')
|
g.typedefs.writeln(', // ${cur_value}')
|
||||||
cur_enum_offset++
|
cur_enum_offset++
|
||||||
}
|
}
|
||||||
|
@ -2221,6 +2211,9 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
||||||
}
|
}
|
||||||
// loop over types
|
// loop over types
|
||||||
for t in typesa {
|
for t in typesa {
|
||||||
|
if t.kind == .interface_ {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// create list of deps
|
// create list of deps
|
||||||
mut field_deps := []string
|
mut field_deps := []string
|
||||||
match t.info {
|
match t.info {
|
||||||
|
@ -2232,6 +2225,9 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
||||||
}
|
}
|
||||||
table.Struct {
|
table.Struct {
|
||||||
info := t.info as table.Struct
|
info := t.info as table.Struct
|
||||||
|
// if info.is_interface {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
dep := g.table.get_type_symbol(field.typ).name
|
dep := g.table.get_type_symbol(field.typ).name
|
||||||
// skip if not in types list or already in deps
|
// skip if not in types list or already in deps
|
||||||
|
@ -2849,12 +2845,12 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn styp_to_str_fn_name(styp string) string {
|
fn styp_to_str_fn_name(styp string) string {
|
||||||
res := styp.replace('.', '__').replace('*','_ptr') + '_str'
|
res := styp.replace('.', '__').replace('*', '_ptr') + '_str'
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// already generated styp, reuse it
|
// already generated styp, reuse it
|
||||||
fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp, str_fn_name string) {
|
||||||
already_generated_key := '${styp}:${str_fn_name}'
|
already_generated_key := '${styp}:${str_fn_name}'
|
||||||
if sym.has_method('str') || already_generated_key in g.str_types {
|
if sym.has_method('str') || already_generated_key in g.str_types {
|
||||||
return
|
return
|
||||||
|
@ -2870,7 +2866,7 @@ fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp string, str_fn_name s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp, str_fn_name string) {
|
||||||
mut convertor := ''
|
mut convertor := ''
|
||||||
mut typename := ''
|
mut typename := ''
|
||||||
if sym.parent_idx in table.integer_type_idxs {
|
if sym.parent_idx in table.integer_type_idxs {
|
||||||
|
@ -2901,7 +2897,7 @@ fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name st
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
||||||
s := styp.replace('.', '__')
|
s := styp.replace('.', '__')
|
||||||
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
||||||
|
@ -2914,27 +2910,29 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
||||||
// TODO: short it if possible
|
// TODO: short it if possible
|
||||||
// generates all definitions of substructs
|
// generates all definitions of substructs
|
||||||
mut fnames2strfunc := map[string]string
|
mut fnames2strfunc := {
|
||||||
|
'': ''
|
||||||
|
} // map[string]string // TODO vfmt bug
|
||||||
for i, field in info.fields {
|
for i, field in info.fields {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] {
|
if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] {
|
||||||
field_styp := g.typ(field.typ)
|
field_styp := g.typ(field.typ)
|
||||||
field_fn_name := styp_to_str_fn_name( field_styp )
|
field_fn_name := styp_to_str_fn_name(field_styp)
|
||||||
fnames2strfunc[ field_styp ] = field_fn_name
|
fnames2strfunc[field_styp] = field_fn_name
|
||||||
g.gen_str_for_type(sym, field_styp, field_fn_name)
|
g.gen_str_for_type(sym, field_styp, field_fn_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.definitions.writeln('string ${str_fn_name}($styp x, int indent_count); // auto')
|
g.definitions.writeln('string ${str_fn_name}($styp x, int indent_count); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x, int indent_count) {')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp x, int indent_count) {')
|
||||||
mut clean_struct_v_type_name := styp.replace('__','.')
|
mut clean_struct_v_type_name := styp.replace('__', '.')
|
||||||
if styp.ends_with('*') {
|
if styp.ends_with('*') {
|
||||||
deref_typ := styp.replace('*', '')
|
deref_typ := styp.replace('*', '')
|
||||||
g.auto_str_funcs.writeln('\t${deref_typ} *it = x;')
|
g.auto_str_funcs.writeln('\t${deref_typ} *it = x;')
|
||||||
clean_struct_v_type_name = '&' + clean_struct_v_type_name.replace('*', '')
|
clean_struct_v_type_name = '&' + clean_struct_v_type_name.replace('*', '')
|
||||||
}else{
|
} else {
|
||||||
deref_typ := styp
|
deref_typ := styp
|
||||||
g.auto_str_funcs.writeln('\t${deref_typ} *it = &x;')
|
g.auto_str_funcs.writeln('\t${deref_typ} *it = &x;')
|
||||||
}
|
}
|
||||||
|
@ -2954,14 +2952,14 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
for i, field in info.fields {
|
for i, field in info.fields {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
has_custom_str := sym.has_method('str')
|
has_custom_str := sym.has_method('str')
|
||||||
second_str_param := if has_custom_str {''} else {', indent_count + 1'}
|
second_str_param := if has_custom_str { '' } else { ', indent_count + 1' }
|
||||||
field_styp := g.typ(field.typ)
|
field_styp := g.typ(field.typ)
|
||||||
field_styp_fn_name := if has_custom_str {'${field_styp}_str'} else {fnames2strfunc[ field_styp ]}
|
field_styp_fn_name := if has_custom_str { '${field_styp}_str' } else { fnames2strfunc[field_styp] }
|
||||||
if sym.kind == .enum_ {
|
if sym.kind == .enum_ {
|
||||||
g.auto_str_funcs.write('indents.len, indents.str, ')
|
g.auto_str_funcs.write('indents.len, indents.str, ')
|
||||||
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name} ).len, ')
|
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name} ).len, ')
|
||||||
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name} ).str ')
|
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name} ).str ')
|
||||||
}else if sym.kind in [.struct_, .array, .array_fixed] {
|
} else if sym.kind in [.struct_, .array, .array_fixed] {
|
||||||
g.auto_str_funcs.write('indents.len, indents.str, ')
|
g.auto_str_funcs.write('indents.len, indents.str, ')
|
||||||
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name}${second_str_param} ).len, ')
|
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name}${second_str_param} ).len, ')
|
||||||
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name}${second_str_param} ).str ')
|
g.auto_str_funcs.write('${field_styp_fn_name}( it->${field.name}${second_str_param} ).str ')
|
||||||
|
@ -2983,11 +2981,11 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_array(info table.Array, styp, str_fn_name string) {
|
||||||
sym := g.table.get_type_symbol(info.elem_type)
|
sym := g.table.get_type_symbol(info.elem_type)
|
||||||
field_styp := g.typ(info.elem_type)
|
field_styp := g.typ(info.elem_type)
|
||||||
if sym.kind == .struct_ && !sym.has_method('str') {
|
if sym.kind == .struct_ && !sym.has_method('str') {
|
||||||
g.gen_str_for_type(sym, field_styp, styp_to_str_fn_name(field_styp) )
|
g.gen_str_for_type(sym, field_styp, styp_to_str_fn_name(field_styp))
|
||||||
}
|
}
|
||||||
g.definitions.writeln('string ${str_fn_name}($styp a); // auto')
|
g.definitions.writeln('string ${str_fn_name}($styp a); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp a) {')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp a) {')
|
||||||
|
@ -3011,7 +3009,7 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_map(info table.Map, styp, str_fn_name string) {
|
||||||
key_sym := g.table.get_type_symbol(info.key_type)
|
key_sym := g.table.get_type_symbol(info.key_type)
|
||||||
key_styp := g.typ(info.key_type)
|
key_styp := g.typ(info.key_type)
|
||||||
if key_sym.kind == .struct_ && !key_sym.has_method('str') {
|
if key_sym.kind == .struct_ && !key_sym.has_method('str') {
|
||||||
|
@ -3068,3 +3066,60 @@ fn (g Gen) type_to_fmt(typ table.Type) string {
|
||||||
}
|
}
|
||||||
return '%d'
|
return '%d'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates interface table and interface indexes
|
||||||
|
fn (v &Gen) interface_table() string {
|
||||||
|
mut sb := strings.new_builder(100)
|
||||||
|
for _, t in v.table.types {
|
||||||
|
if t.kind != .interface_ {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info := t.info as table.Interface
|
||||||
|
// interface_name is for example Speaker
|
||||||
|
interface_name := t.name
|
||||||
|
mut methods := ''
|
||||||
|
mut generated_casting_functions := ''
|
||||||
|
sb.writeln('// NR gen_types= $info.gen_types.len')
|
||||||
|
for i, gen_type in info.gen_types {
|
||||||
|
// ptr_ctype can be for example Cat OR Cat_ptr:
|
||||||
|
ptr_ctype := gen_type.replace('*', '_ptr')
|
||||||
|
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||||
|
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||||
|
cctype := gen_type.replace('*', '')
|
||||||
|
// Speaker_Cat_index = 0
|
||||||
|
interface_index_name := '_${interface_name}_${ptr_ctype}_index'
|
||||||
|
generated_casting_functions += '
|
||||||
|
${interface_name} I_${cctype}_to_${interface_name}(${cctype} x) {
|
||||||
|
return (${interface_name}){
|
||||||
|
._object = (void*) memdup(&x, sizeof(${cctype})),
|
||||||
|
._interface_idx = ${interface_index_name} };
|
||||||
|
}
|
||||||
|
'
|
||||||
|
methods += '{\n'
|
||||||
|
for j, method in t.methods {
|
||||||
|
// Cat_speak
|
||||||
|
methods += ' (void*) ${cctype}_${method.name}'
|
||||||
|
if j < t.methods.len - 1 {
|
||||||
|
methods += ', \n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
methods += '\n},\n\n'
|
||||||
|
sb.writeln('int ${interface_index_name} = $i;')
|
||||||
|
}
|
||||||
|
if info.gen_types.len > 0 {
|
||||||
|
// methods = '{TCCSKIP(0)}'
|
||||||
|
// }
|
||||||
|
sb.writeln('void* (* ${interface_name}_name_table[][$t.methods.len]) = ' + '{ \n $methods \n }; ')
|
||||||
|
} else {
|
||||||
|
// The line below is needed so that C compilation succeeds,
|
||||||
|
// even if no interface methods are called.
|
||||||
|
// See https://github.com/zenith391/vgtk3/issues/7
|
||||||
|
sb.writeln('void* (* ${interface_name}_name_table[][1]) = ' + '{ {NULL} }; ')
|
||||||
|
}
|
||||||
|
if generated_casting_functions.len > 0 {
|
||||||
|
sb.writeln('// Casting functions for interface "${interface_name}" :')
|
||||||
|
sb.writeln(generated_casting_functions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.str()
|
||||||
|
}
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module gen
|
module gen
|
||||||
|
|
||||||
import (
|
import v.ast
|
||||||
v.ast
|
import v.table
|
||||||
v.table
|
import v.util
|
||||||
v.util
|
|
||||||
)
|
|
||||||
|
|
||||||
fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if it.is_c {
|
if it.is_c {
|
||||||
// || it.no_body {
|
// || it.no_body {
|
||||||
return
|
return
|
||||||
|
@ -88,7 +86,6 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.writeln('\tint ___argc;')
|
g.writeln('\tint ___argc;')
|
||||||
g.writeln('\twchar_t** ___argv = CommandLineToArgvW(cmd_line, &___argc);')
|
g.writeln('\twchar_t** ___argv = CommandLineToArgvW(cmd_line, &___argc);')
|
||||||
}
|
}
|
||||||
|
|
||||||
g.writeln('\t_vinit();')
|
g.writeln('\t_vinit();')
|
||||||
if g.is_importing_os() {
|
if g.is_importing_os() {
|
||||||
if g.autofree {
|
if g.autofree {
|
||||||
|
@ -126,7 +123,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.fn_decl = 0
|
g.fn_decl = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) {
|
fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) {
|
||||||
no_names := args.len > 0 && args[0].name == 'arg_1'
|
no_names := args.len > 0 && args[0].name == 'arg_1'
|
||||||
for i, arg in args {
|
for i, arg in args {
|
||||||
arg_type_sym := g.table.get_type_symbol(arg.typ)
|
arg_type_sym := g.table.get_type_symbol(arg.typ)
|
||||||
|
@ -175,7 +172,7 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) call_expr(node ast.CallExpr) {
|
fn (mut g Gen) call_expr(node ast.CallExpr) {
|
||||||
gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0
|
gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0
|
||||||
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
||||||
if gen_or {
|
if gen_or {
|
||||||
|
@ -192,21 +189,37 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) method_call(node ast.CallExpr) {
|
fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
if node.left_type == 0 {
|
if node.left_type == 0 {
|
||||||
verror('method receiver type is 0, this means there are some uchecked exprs')
|
verror('method receiver type is 0, this means there are some uchecked exprs')
|
||||||
}
|
}
|
||||||
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
|
||||||
mut receiver_name := typ_sym.name
|
mut receiver_name := typ_sym.name
|
||||||
|
if typ_sym.kind == .interface_ {
|
||||||
|
g.writeln('// interface method call')
|
||||||
|
// `((void (*)())(Speaker_name_table[s._interface_idx][1]))(s._object);`
|
||||||
|
g.write('((void (*)())(${receiver_name}_name_table[')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write('._interface_idx][1]))(')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.writeln('._object );')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
if typ_sym.kind == .array && node.name == 'filter' {
|
if typ_sym.kind == .array && node.name == 'filter' {
|
||||||
g.gen_filter(node)
|
g.gen_filter(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO performance, detect `array` method differently
|
// TODO performance, detect `array` method differently
|
||||||
if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many',
|
if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many',
|
||||||
'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
'trim'
|
||||||
|
'first'
|
||||||
|
'last'
|
||||||
|
'clone'
|
||||||
|
'reverse'
|
||||||
|
'slice'
|
||||||
|
] {
|
||||||
// && rec_sym.name == 'array' {
|
// && rec_sym.name == 'array' {
|
||||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||||
// `array_byte_clone` => `array_clone`
|
// `array_byte_clone` => `array_clone`
|
||||||
|
@ -255,7 +268,7 @@ fn (g mut Gen) method_call(node ast.CallExpr) {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) fn_call(node ast.CallExpr) {
|
fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
// call struct field with fn type
|
// call struct field with fn type
|
||||||
// TODO: test node.left instead
|
// TODO: test node.left instead
|
||||||
// left & left_type will be `x` and `x type` in `x.fieldfn()`
|
// left & left_type will be `x` and `x type` in `x.fieldfn()`
|
||||||
|
@ -264,8 +277,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
if table.type_is_ptr(node.left_type) {
|
if table.type_is_ptr(node.left_type) {
|
||||||
g.write('->')
|
g.write('->')
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
g.write('.')
|
g.write('.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,15 +334,9 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
} else {
|
} else {
|
||||||
expr := node.args[0].expr
|
expr := node.args[0].expr
|
||||||
is_var := match expr {
|
is_var := match expr {
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr { true }
|
||||||
true
|
ast.Ident { true }
|
||||||
}
|
else { false }
|
||||||
ast.Ident {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if table.type_is_ptr(typ) && sym.kind != .struct_ {
|
if table.type_is_ptr(typ) && sym.kind != .struct_ {
|
||||||
// ptr_str() for pointers
|
// ptr_str() for pointers
|
||||||
|
@ -381,10 +387,10 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||||
is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len -
|
is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len -
|
||||||
1], .variadic)
|
1], .variadic)
|
||||||
is_forwarding_varg := args.len > 0 && table.type_is(args[args.len-1].typ, .variadic)
|
is_forwarding_varg := args.len > 0 && table.type_is(args[args.len - 1].typ, .variadic)
|
||||||
gen_vargs := is_variadic && !is_forwarding_varg
|
gen_vargs := is_variadic && !is_forwarding_varg
|
||||||
mut arg_no := 0
|
mut arg_no := 0
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -427,7 +433,7 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
||||||
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
||||||
expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs
|
expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs
|
||||||
if arg.is_mut && !arg_is_ptr {
|
if arg.is_mut && !arg_is_ptr {
|
||||||
|
@ -454,7 +460,7 @@ fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
||||||
g.expr_with_cast(arg.expr, arg.typ, expected_type)
|
g.expr_with_cast(arg.expr, arg.typ, expected_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) is_gui_app() bool {
|
fn (mut g Gen) is_gui_app() bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
for cf in g.table.cflags {
|
for cf in g.table.cflags {
|
||||||
if cf.value == 'gdi32' {
|
if cf.value == 'gdi32' {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import v.ast
|
||||||
import v.table
|
import v.table
|
||||||
import v.token
|
import v.token
|
||||||
|
|
||||||
fn (var p Parser) struct_decl() ast.StructDecl {
|
fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||||
start_pos := p.tok.position()
|
start_pos := p.tok.position()
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
if is_pub {
|
if is_pub {
|
||||||
|
@ -31,17 +31,17 @@ fn (var p Parser) struct_decl() ast.StructDecl {
|
||||||
p.error('`$p.tok.lit` lacks body')
|
p.error('`$p.tok.lit` lacks body')
|
||||||
}
|
}
|
||||||
end_pos := p.tok.position()
|
end_pos := p.tok.position()
|
||||||
var name := p.check_name()
|
mut name := p.check_name()
|
||||||
// println('struct decl $name')
|
// println('struct decl $name')
|
||||||
var ast_fields := []ast.StructField
|
mut ast_fields := []ast.StructField
|
||||||
var fields := []table.Field
|
mut fields := []table.Field
|
||||||
var mut_pos := -1
|
mut mut_pos := -1
|
||||||
var pub_pos := -1
|
mut pub_pos := -1
|
||||||
var pub_mut_pos := -1
|
mut pub_mut_pos := -1
|
||||||
if !no_body {
|
if !no_body {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
for p.tok.kind != .rcbr {
|
for p.tok.kind != .rcbr {
|
||||||
var comment := ast.Comment{}
|
mut comment := ast.Comment{}
|
||||||
if p.tok.kind == .comment {
|
if p.tok.kind == .comment {
|
||||||
comment = p.comment()
|
comment = p.comment()
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ fn (var p Parser) struct_decl() ast.StructDecl {
|
||||||
println('XXXX' + s.str())
|
println('XXXX' + s.str())
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
var default_expr := ast.Expr{}
|
mut default_expr := ast.Expr{}
|
||||||
var has_default_expr := false
|
mut has_default_expr := false
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
// Default value
|
// Default value
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -81,15 +81,13 @@ fn (var p Parser) struct_decl() ast.StructDecl {
|
||||||
// p.expr(0)
|
// p.expr(0)
|
||||||
default_expr = p.expr(0)
|
default_expr = p.expr(0)
|
||||||
match default_expr {
|
match default_expr {
|
||||||
ast.EnumVal {
|
ast.EnumVal { it.typ = typ }
|
||||||
it.typ = typ
|
|
||||||
}
|
|
||||||
// TODO: implement all types??
|
// TODO: implement all types??
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
has_default_expr = true
|
has_default_expr = true
|
||||||
}
|
}
|
||||||
var attr := ast.Attr{}
|
mut attr := ast.Attr{}
|
||||||
if p.tok.kind == .lsbr {
|
if p.tok.kind == .lsbr {
|
||||||
attr = p.attribute()
|
attr = p.attribute()
|
||||||
}
|
}
|
||||||
|
@ -132,7 +130,7 @@ fn (var p Parser) struct_decl() ast.StructDecl {
|
||||||
}
|
}
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
}
|
}
|
||||||
var ret := 0
|
mut ret := 0
|
||||||
if p.builtin_mod && t.name in table.builtin_type_names {
|
if p.builtin_mod && t.name in table.builtin_type_names {
|
||||||
// this allows overiding the builtins type
|
// this allows overiding the builtins type
|
||||||
// with the real struct type info parsed from builtin
|
// with the real struct type info parsed from builtin
|
||||||
|
@ -158,7 +156,7 @@ fn (var p Parser) struct_decl() ast.StructDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
first_pos := p.tok.position()
|
first_pos := p.tok.position()
|
||||||
typ := if short_syntax { table.void_type } else { p.parse_type() }
|
typ := if short_syntax { table.void_type } else { p.parse_type() }
|
||||||
p.expr_mod = ''
|
p.expr_mod = ''
|
||||||
|
@ -167,17 +165,17 @@ fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
if !short_syntax {
|
if !short_syntax {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
}
|
}
|
||||||
var fields := []ast.StructInitField
|
mut fields := []ast.StructInitField
|
||||||
var i := 0
|
mut i := 0
|
||||||
is_short_syntax := p.peek_tok.kind != .colon && p.tok.kind != .rcbr // `Vec{a,b,c}
|
is_short_syntax := p.peek_tok.kind != .colon && p.tok.kind != .rcbr // `Vec{a,b,c}
|
||||||
// p.warn(is_short_syntax.str())
|
// p.warn(is_short_syntax.str())
|
||||||
for p.tok.kind != .rcbr {
|
for p.tok.kind != .rcbr {
|
||||||
p.check_comment()
|
p.check_comment()
|
||||||
var field_name := ''
|
mut field_name := ''
|
||||||
if is_short_syntax {
|
if is_short_syntax {
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
fields << ast.StructInitField{
|
|
||||||
// name will be set later in checker
|
// name will be set later in checker
|
||||||
|
fields << ast.StructInitField{
|
||||||
expr: expr
|
expr: expr
|
||||||
pos: expr.position()
|
pos: expr.position()
|
||||||
}
|
}
|
||||||
|
@ -221,28 +219,57 @@ fn (var p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (var p Parser) interface_decl() ast.InterfaceDecl {
|
fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
if is_pub {
|
if is_pub {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
p.next() // `interface`
|
p.next() // `interface`
|
||||||
interface_name := p.check_name()
|
interface_name := p.check_name()
|
||||||
|
//println('interface decl $interface_name')
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
var field_names := []string
|
// Declare the type
|
||||||
|
t := table.TypeSymbol{
|
||||||
|
kind: .interface_
|
||||||
|
name: interface_name
|
||||||
|
info: table.Struct{
|
||||||
|
//is_interface: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typ := p.table.register_type_symbol(t)
|
||||||
|
ts := p.table.get_type_symbol(typ) // TODO t vs ts
|
||||||
|
// Parse methods
|
||||||
|
mut methods := []ast.FnDecl
|
||||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||||
line_nr := p.tok.line_nr
|
line_nr := p.tok.line_nr
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
field_names << name
|
println(name)
|
||||||
p.fn_args()
|
// field_names << name
|
||||||
if p.tok.kind == .name && p.tok.line_nr == line_nr {
|
args2, _ := p.fn_args()
|
||||||
p.parse_type()
|
mut args := [table.Arg{
|
||||||
|
name: 'x'
|
||||||
|
typ: typ
|
||||||
|
}]
|
||||||
|
args << args2
|
||||||
|
mut method := ast.FnDecl{
|
||||||
|
name: name
|
||||||
|
args: args
|
||||||
|
return_type: table.void_type
|
||||||
}
|
}
|
||||||
|
if p.tok.kind == .name && p.tok.line_nr == line_nr {
|
||||||
|
method.return_type = p.parse_type()
|
||||||
|
}
|
||||||
|
methods << method
|
||||||
|
//println('register method $name')
|
||||||
|
ts.register_method(table.Fn{
|
||||||
|
name: name
|
||||||
|
args: args
|
||||||
|
return_type: method.return_type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
return ast.InterfaceDecl{
|
return ast.InterfaceDecl{
|
||||||
name: interface_name
|
name: interface_name
|
||||||
field_names: field_names
|
methods: methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import v.ast
|
||||||
|
|
||||||
pub type Type int
|
pub type Type int
|
||||||
|
|
||||||
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Alias | Enum | SumType | FnType
|
pub type TypeInfo = Array | ArrayFixed | Map | Struct | Interface | MultiReturn | Alias | Enum | SumType | FnType
|
||||||
|
|
||||||
pub struct TypeSymbol {
|
pub struct TypeSymbol {
|
||||||
pub:
|
pub:
|
||||||
|
@ -160,10 +160,18 @@ pub const (
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||||
u16_type_idx, u32_type_idx, u64_type_idx]
|
u16_type_idx
|
||||||
|
u32_type_idx
|
||||||
|
u64_type_idx
|
||||||
|
]
|
||||||
float_type_idxs = [f32_type_idx, f64_type_idx]
|
float_type_idxs = [f32_type_idx, f64_type_idx]
|
||||||
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||||
u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx]
|
u16_type_idx
|
||||||
|
u32_type_idx
|
||||||
|
u64_type_idx
|
||||||
|
f32_type_idx
|
||||||
|
f64_type_idx
|
||||||
|
]
|
||||||
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
||||||
string_type_idxs = [string_type_idx, ustring_type_idx]
|
string_type_idxs = [string_type_idx, ustring_type_idx]
|
||||||
)
|
)
|
||||||
|
@ -194,8 +202,10 @@ pub const (
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64',
|
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64',
|
||||||
'u16', 'u32', 'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
|
'u16'
|
||||||
'map', 'struct', 'mapnode', 'size_t']
|
'u32', 'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array',
|
||||||
|
'array_fixed', 'map'
|
||||||
|
'struct', 'mapnode', 'size_t']
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
|
@ -242,6 +252,7 @@ pub enum Kind {
|
||||||
alias
|
alias
|
||||||
enum_
|
enum_
|
||||||
function
|
function
|
||||||
|
interface_
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &TypeSymbol) str() string {
|
pub fn (t &TypeSymbol) str() string {
|
||||||
|
@ -251,60 +262,40 @@ pub fn (t &TypeSymbol) str() string {
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) enum_info() Enum {
|
pub fn (t &TypeSymbol) enum_info() Enum {
|
||||||
match t.info {
|
match t.info {
|
||||||
Enum {
|
Enum { return it }
|
||||||
return it
|
else { panic('TypeSymbol.enum_info(): no enum info for type: $t.name') }
|
||||||
}
|
|
||||||
else {
|
|
||||||
panic('TypeSymbol.enum_info(): no enum info for type: $t.name')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) mr_info() MultiReturn {
|
pub fn (t &TypeSymbol) mr_info() MultiReturn {
|
||||||
match t.info {
|
match t.info {
|
||||||
MultiReturn {
|
MultiReturn { return it }
|
||||||
return it
|
else { panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') }
|
||||||
}
|
|
||||||
else {
|
|
||||||
panic('TypeSymbol.mr_info(): no multi return info for type: $t.name')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) array_info() Array {
|
pub fn (t &TypeSymbol) array_info() Array {
|
||||||
match t.info {
|
match t.info {
|
||||||
Array {
|
Array { return it }
|
||||||
return it
|
else { panic('TypeSymbol.array_info(): no array info for type: $t.name') }
|
||||||
}
|
|
||||||
else {
|
|
||||||
panic('TypeSymbol.array_info(): no array info for type: $t.name')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed {
|
pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed {
|
||||||
match t.info {
|
match t.info {
|
||||||
ArrayFixed {
|
ArrayFixed { return it }
|
||||||
return it
|
else { panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') }
|
||||||
}
|
|
||||||
else {
|
|
||||||
panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &TypeSymbol) map_info() Map {
|
pub fn (t &TypeSymbol) map_info() Map {
|
||||||
match t.info {
|
match t.info {
|
||||||
Map {
|
Map { return it }
|
||||||
return it
|
else { panic('TypeSymbol.map_info(): no map info for type: $t.name') }
|
||||||
}
|
|
||||||
else {
|
|
||||||
panic('TypeSymbol.map_info(): no map info for type: $t.name')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +304,7 @@ pub fn (t TypeSymbol) str() string {
|
||||||
return t.name
|
return t.name
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
pub fn (var t Table) register_builtin_type_symbols() {
|
pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
// reserve index 0 so nothing can go there
|
// reserve index 0 so nothing can go there
|
||||||
// save index check, 0 will mean not found
|
// save index check, 0 will mean not found
|
||||||
t.register_type_symbol(TypeSymbol{
|
t.register_type_symbol(TypeSymbol{
|
||||||
|
@ -445,99 +436,40 @@ pub fn (t &TypeSymbol) is_number() bool {
|
||||||
|
|
||||||
pub fn (k Kind) str() string {
|
pub fn (k Kind) str() string {
|
||||||
k_str := match k {
|
k_str := match k {
|
||||||
.placeholder {
|
.placeholder { 'placeholder' }
|
||||||
'placeholder'
|
.void { 'void' }
|
||||||
}
|
.voidptr { 'voidptr' }
|
||||||
.void {
|
.charptr { 'charptr' }
|
||||||
'void'
|
.byteptr { 'byteptr' }
|
||||||
}
|
.struct_ { 'struct' }
|
||||||
.voidptr {
|
.int { 'int' }
|
||||||
'voidptr'
|
.i8 { 'i8' }
|
||||||
}
|
.i16 { 'i16' }
|
||||||
.charptr {
|
.i64 { 'i64' }
|
||||||
'charptr'
|
.byte { 'byte' }
|
||||||
}
|
.u16 { 'u16' }
|
||||||
.byteptr {
|
.u32 { 'u32' }
|
||||||
'byteptr'
|
.u64 { 'u64' }
|
||||||
}
|
.f32 { 'f32' }
|
||||||
.struct_ {
|
.f64 { 'f64' }
|
||||||
'struct'
|
.string { 'string' }
|
||||||
}
|
.char { 'char' }
|
||||||
.int {
|
.bool { 'bool' }
|
||||||
'int'
|
.none_ { 'none' }
|
||||||
}
|
.array { 'array' }
|
||||||
.i8 {
|
.array_fixed { 'array_fixed' }
|
||||||
'i8'
|
.map { 'map' }
|
||||||
}
|
.multi_return { 'multi_return' }
|
||||||
.i16 {
|
.sum_type { 'sum_type' }
|
||||||
'i16'
|
.alias { 'alias' }
|
||||||
}
|
.enum_ { 'enum' }
|
||||||
.i64 {
|
else { 'unknown' }
|
||||||
'i64'
|
|
||||||
}
|
|
||||||
.byte {
|
|
||||||
'byte'
|
|
||||||
}
|
|
||||||
.u16 {
|
|
||||||
'u16'
|
|
||||||
}
|
|
||||||
.u32 {
|
|
||||||
'u32'
|
|
||||||
}
|
|
||||||
.u64 {
|
|
||||||
'u64'
|
|
||||||
}
|
|
||||||
.f32 {
|
|
||||||
'f32'
|
|
||||||
}
|
|
||||||
.f64 {
|
|
||||||
'f64'
|
|
||||||
}
|
|
||||||
.string {
|
|
||||||
'string'
|
|
||||||
}
|
|
||||||
.ustring {
|
|
||||||
'ustring'
|
|
||||||
}
|
|
||||||
.char {
|
|
||||||
'char'
|
|
||||||
}
|
|
||||||
.bool {
|
|
||||||
'bool'
|
|
||||||
}
|
|
||||||
.none_ {
|
|
||||||
'none'
|
|
||||||
}
|
|
||||||
.array {
|
|
||||||
'array'
|
|
||||||
}
|
|
||||||
.array_fixed {
|
|
||||||
'array_fixed'
|
|
||||||
}
|
|
||||||
.map {
|
|
||||||
'map'
|
|
||||||
}
|
|
||||||
.multi_return {
|
|
||||||
'multi_return'
|
|
||||||
}
|
|
||||||
.sum_type {
|
|
||||||
'sum_type'
|
|
||||||
}
|
|
||||||
.alias {
|
|
||||||
'alias'
|
|
||||||
}
|
|
||||||
.enum_ {
|
|
||||||
'enum'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
'unknown'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return k_str
|
return k_str
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (kinds []Kind) str() string {
|
pub fn (kinds []Kind) str() string {
|
||||||
var kinds_str := ''
|
mut kinds_str := ''
|
||||||
for i, k in kinds {
|
for i, k in kinds {
|
||||||
kinds_str += k.str()
|
kinds_str += k.str()
|
||||||
if i < kinds.len - 1 {
|
if i < kinds.len - 1 {
|
||||||
|
@ -554,6 +486,10 @@ pub mut:
|
||||||
is_union bool
|
is_union bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Interface {
|
||||||
|
gen_types []string
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Enum {
|
pub struct Enum {
|
||||||
pub:
|
pub:
|
||||||
vals []string
|
vals []string
|
||||||
|
@ -604,7 +540,7 @@ pub:
|
||||||
pub fn (table &Table) type_to_str(t Type) string {
|
pub fn (table &Table) type_to_str(t Type) string {
|
||||||
sym := table.get_type_symbol(t)
|
sym := table.get_type_symbol(t)
|
||||||
if sym.kind == .multi_return {
|
if sym.kind == .multi_return {
|
||||||
var res := '('
|
mut res := '('
|
||||||
mr_info := sym.info as MultiReturn
|
mr_info := sym.info as MultiReturn
|
||||||
for i, typ in mr_info.types {
|
for i, typ in mr_info.types {
|
||||||
res += table.type_to_str(typ)
|
res += table.type_to_str(typ)
|
||||||
|
@ -615,7 +551,7 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||||
res += ')'
|
res += ')'
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
var res := sym.name
|
mut res := sym.name
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
res = res.replace('array_', '[]')
|
res = res.replace('array_', '[]')
|
||||||
} else if sym.kind == .map {
|
} else if sym.kind == .map {
|
||||||
|
|
|
@ -22,12 +22,40 @@ fn (d Dog) name() string {
|
||||||
return 'Dog'
|
return 'Dog'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_todo() {}
|
fn test_todo() {
|
||||||
|
if true {}
|
||||||
|
//
|
||||||
|
else{}
|
||||||
|
}
|
||||||
|
|
||||||
interface Speaker {
|
interface Speaker {
|
||||||
name ()string
|
name() string
|
||||||
speak()
|
speak()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn perform_speak(s Speaker) {
|
||||||
|
s.speak()
|
||||||
|
assert true
|
||||||
|
/*
|
||||||
|
name := s.name()
|
||||||
|
assert name == 'Dog' || name == 'Cat'
|
||||||
|
println(s.name())
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_perform_speak() {
|
||||||
|
dog := Dog{}
|
||||||
|
perform_speak(dog)
|
||||||
|
cat := Cat{}
|
||||||
|
perform_speak(cat)
|
||||||
|
// perform_speakers([dog, cat])
|
||||||
|
/*
|
||||||
|
f := Foo {
|
||||||
|
speaker: dog
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
interface Speak2er {
|
interface Speak2er {
|
||||||
|
@ -40,37 +68,8 @@ struct Foo {
|
||||||
speakers []Speaker
|
speakers []Speaker
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_speak(s Speaker) {
|
|
||||||
if true {
|
|
||||||
// QTODO
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.speak()
|
|
||||||
assert true
|
|
||||||
name := s.name()
|
|
||||||
assert name == 'Dog' || name == 'Cat'
|
|
||||||
println(s.name())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn perform_speakers(speakers []Speaker) {}
|
fn perform_speakers(speakers []Speaker) {}
|
||||||
|
|
||||||
fn test_perform_speak() {
|
|
||||||
if true {
|
|
||||||
// QTODO
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dog := Dog{}
|
|
||||||
perform_speak(dog)
|
|
||||||
cat := Cat{}
|
|
||||||
perform_speak(cat)
|
|
||||||
// perform_speakers([dog, cat])
|
|
||||||
/*
|
|
||||||
f := Foo {
|
|
||||||
speaker: dog
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Register {
|
interface Register {
|
||||||
register()}
|
register()}
|
||||||
|
@ -93,3 +92,4 @@ fn test_register() {
|
||||||
handle_reg(f)
|
handle_reg(f)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue