|
|
|
@ -51,6 +51,7 @@ struct Gen {
|
|
|
|
|
includes strings.Builder // all C #includes required by V modules
|
|
|
|
|
typedefs strings.Builder
|
|
|
|
|
typedefs2 strings.Builder
|
|
|
|
|
type_definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file)
|
|
|
|
|
definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file)
|
|
|
|
|
inits strings.Builder // contents of `void _vinit(){}`
|
|
|
|
|
cleanups strings.Builder // contents of `void _vcleanup(){}`
|
|
|
|
@ -60,6 +61,7 @@ struct Gen {
|
|
|
|
|
comptime_defines strings.Builder // custom defines, given by -d/-define flags on the CLI
|
|
|
|
|
pcs_declarations strings.Builder // -prof profile counter declarations for each function
|
|
|
|
|
hotcode_definitions strings.Builder // -live declarations & functions
|
|
|
|
|
options strings.Builder // `Option_xxxx` types
|
|
|
|
|
table &table.Table
|
|
|
|
|
pref &pref.Preferences
|
|
|
|
|
module_built string
|
|
|
|
@ -116,6 +118,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|
|
|
|
includes: strings.new_builder(100)
|
|
|
|
|
typedefs: strings.new_builder(100)
|
|
|
|
|
typedefs2: strings.new_builder(100)
|
|
|
|
|
type_definitions: strings.new_builder(100)
|
|
|
|
|
definitions: strings.new_builder(100)
|
|
|
|
|
gowrappers: strings.new_builder(100)
|
|
|
|
|
stringliterals: strings.new_builder(100)
|
|
|
|
@ -125,6 +128,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|
|
|
|
cleanups: strings.new_builder(100)
|
|
|
|
|
pcs_declarations: strings.new_builder(100)
|
|
|
|
|
hotcode_definitions: strings.new_builder(100)
|
|
|
|
|
options: strings.new_builder(100)
|
|
|
|
|
table: table
|
|
|
|
|
pref: pref
|
|
|
|
|
fn_decl: 0
|
|
|
|
@ -185,6 +189,10 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|
|
|
|
b.writeln(g.cheaders.str())
|
|
|
|
|
b.writeln('\n// V includes:')
|
|
|
|
|
b.writeln(g.includes.str())
|
|
|
|
|
b.writeln('\n// V type definitions:')
|
|
|
|
|
b.writeln(g.type_definitions.str())
|
|
|
|
|
b.writeln('\n// V Option_xxx definitions:')
|
|
|
|
|
b.writeln(g.options.str())
|
|
|
|
|
b.writeln('\n// V definitions:')
|
|
|
|
|
b.writeln(g.definitions.str())
|
|
|
|
|
b.writeln('\n// V profile counters:')
|
|
|
|
@ -309,20 +317,9 @@ fn (mut g Gen) typ(t table.Type) string {
|
|
|
|
|
// T => int etc
|
|
|
|
|
return g.typ(g.cur_generic_type)
|
|
|
|
|
}
|
|
|
|
|
base := styp
|
|
|
|
|
if t.flag_is(.optional) {
|
|
|
|
|
if t.is_ptr() {
|
|
|
|
|
styp = styp.replace('*', '_ptr')
|
|
|
|
|
}
|
|
|
|
|
styp = 'Option_' + styp
|
|
|
|
|
// Register an optional if it's not registered yet
|
|
|
|
|
if styp !in g.optionals {
|
|
|
|
|
g.register_optional(t, base)
|
|
|
|
|
// println(styp)
|
|
|
|
|
x := styp // .replace('*', '_ptr') // handle option ptrs
|
|
|
|
|
g.typedefs2.writeln('typedef Option $x;')
|
|
|
|
|
g.optionals << styp
|
|
|
|
|
}
|
|
|
|
|
return g.register_optional(t)
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
if styp.starts_with('C__') {
|
|
|
|
@ -341,17 +338,58 @@ fn (g &Gen) base_type(t table.Type) string {
|
|
|
|
|
return styp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn (mut g Gen) register_optional(t table.Type, styp string) {
|
|
|
|
|
// TODO this really shouldnt be seperate from typ
|
|
|
|
|
// but I(emily) would rather have this generation
|
|
|
|
|
// all unified in one place so that it doesnt break
|
|
|
|
|
// if one location changes
|
|
|
|
|
fn (g &Gen) optional_type_name(t table.Type) (string, string) {
|
|
|
|
|
base := g.base_type(t)
|
|
|
|
|
mut styp := 'Option_$base'
|
|
|
|
|
if t.is_ptr() {
|
|
|
|
|
styp = styp.replace('*', '_ptr')
|
|
|
|
|
}
|
|
|
|
|
return styp, base
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn (g &Gen) optional_type_text(styp, base string) string {
|
|
|
|
|
x := styp // .replace('*', '_ptr') // handle option ptrs
|
|
|
|
|
// replace void with something else
|
|
|
|
|
size := if base == 'void' {
|
|
|
|
|
'int'
|
|
|
|
|
} else {
|
|
|
|
|
base
|
|
|
|
|
}
|
|
|
|
|
ret := 'struct $x {
|
|
|
|
|
bool ok;
|
|
|
|
|
bool is_none;
|
|
|
|
|
string v_error;
|
|
|
|
|
int ecode;
|
|
|
|
|
byte data[sizeof($size)];
|
|
|
|
|
} '
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn (mut g Gen) register_optional(t table.Type) string {
|
|
|
|
|
// g.typedefs2.writeln('typedef Option $x;')
|
|
|
|
|
no_ptr := styp.replace('*', '_ptr')
|
|
|
|
|
typ := if styp == 'void' { 'void*' } else { styp }
|
|
|
|
|
g.hotcode_definitions.writeln('typedef struct {
|
|
|
|
|
$typ data;
|
|
|
|
|
string error;
|
|
|
|
|
int ecode;
|
|
|
|
|
bool ok;
|
|
|
|
|
bool is_none;
|
|
|
|
|
} Option2_$no_ptr;')
|
|
|
|
|
styp, base := g.optional_type_name(t)
|
|
|
|
|
if styp !in g.optionals {
|
|
|
|
|
no_ptr := base.replace('*', '_ptr')
|
|
|
|
|
typ := if base == 'void' { 'void*' } else { base }
|
|
|
|
|
g.hotcode_definitions.writeln('typedef struct {
|
|
|
|
|
$typ data;
|
|
|
|
|
string error;
|
|
|
|
|
int ecode;
|
|
|
|
|
bool ok;
|
|
|
|
|
bool is_none;
|
|
|
|
|
} Option2_$no_ptr;')
|
|
|
|
|
|
|
|
|
|
// println(styp)
|
|
|
|
|
g.typedefs2.writeln('typedef struct $styp $styp;')
|
|
|
|
|
g.options.write(g.optional_type_text(styp, base))
|
|
|
|
|
g.options.writeln(';\n')
|
|
|
|
|
g.optionals << styp
|
|
|
|
|
}
|
|
|
|
|
return styp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cc_type returns the Cleaned Concrete Type name, *without ptr*,
|
|
|
|
@ -388,18 +426,18 @@ typedef struct {
|
|
|
|
|
`.`
|
|
|
|
|
parent_styp := if is_c_parent { 'struct ' + parent.name[2..].replace('.', '__') } else { parent.name.replace('.',
|
|
|
|
|
'__') }
|
|
|
|
|
g.definitions.writeln('typedef $parent_styp $styp;')
|
|
|
|
|
g.type_definitions.writeln('typedef $parent_styp $styp;')
|
|
|
|
|
}
|
|
|
|
|
.array {
|
|
|
|
|
styp := typ.name.replace('.', '__')
|
|
|
|
|
g.definitions.writeln('typedef array $styp;')
|
|
|
|
|
g.type_definitions.writeln('typedef array $styp;')
|
|
|
|
|
}
|
|
|
|
|
.interface_ {
|
|
|
|
|
g.definitions.writeln('typedef _Interface ${c_name(typ.name)};')
|
|
|
|
|
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
|
|
|
|
|
}
|
|
|
|
|
.map {
|
|
|
|
|
styp := typ.name.replace('.', '__')
|
|
|
|
|
g.definitions.writeln('typedef map $styp;')
|
|
|
|
|
g.type_definitions.writeln('typedef map $styp;')
|
|
|
|
|
}
|
|
|
|
|
.function {
|
|
|
|
|
info := typ.info as table.FnType
|
|
|
|
@ -416,14 +454,14 @@ typedef struct {
|
|
|
|
|
} else {
|
|
|
|
|
c_name(func.name)
|
|
|
|
|
}
|
|
|
|
|
g.definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
|
|
|
|
g.type_definitions.write('typedef ${g.typ(func.return_type)} (*$fn_name)(')
|
|
|
|
|
for i, arg in func.args {
|
|
|
|
|
g.definitions.write(g.typ(arg.typ))
|
|
|
|
|
g.type_definitions.write(g.typ(arg.typ))
|
|
|
|
|
if i < func.args.len - 1 {
|
|
|
|
|
g.definitions.write(',')
|
|
|
|
|
g.type_definitions.write(',')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln(');')
|
|
|
|
|
g.type_definitions.writeln(');')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@ -434,7 +472,7 @@ typedef struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (mut g Gen) write_multi_return_types() {
|
|
|
|
|
g.definitions.writeln('// multi return structs')
|
|
|
|
|
g.type_definitions.writeln('// multi return structs')
|
|
|
|
|
for typ in g.table.types {
|
|
|
|
|
// sym := g.table.get_type_symbol(typ)
|
|
|
|
|
if typ.kind != .multi_return {
|
|
|
|
@ -442,30 +480,30 @@ pub fn (mut g Gen) write_multi_return_types() {
|
|
|
|
|
}
|
|
|
|
|
name := typ.name.replace('.', '__')
|
|
|
|
|
info := typ.info as table.MultiReturn
|
|
|
|
|
g.definitions.writeln('typedef struct {')
|
|
|
|
|
g.type_definitions.writeln('typedef struct {')
|
|
|
|
|
// TODO copy pasta StructDecl
|
|
|
|
|
// for field in struct_info.fields {
|
|
|
|
|
for i, mr_typ in info.types {
|
|
|
|
|
type_name := g.typ(mr_typ)
|
|
|
|
|
g.definitions.writeln('\t$type_name arg${i};')
|
|
|
|
|
g.type_definitions.writeln('\t$type_name arg${i};')
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('} $name;\n')
|
|
|
|
|
g.type_definitions.writeln('} $name;\n')
|
|
|
|
|
// g.typedefs.writeln('typedef struct $name $name;')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (mut g Gen) write_variadic_types() {
|
|
|
|
|
if g.variadic_args.size > 0 {
|
|
|
|
|
g.definitions.writeln('// variadic structs')
|
|
|
|
|
g.type_definitions.writeln('// variadic structs')
|
|
|
|
|
}
|
|
|
|
|
for type_str, arg_len in g.variadic_args {
|
|
|
|
|
typ := table.Type(type_str.int())
|
|
|
|
|
type_name := g.typ(typ)
|
|
|
|
|
struct_name := 'varg_' + type_name.replace('*', '_ptr')
|
|
|
|
|
g.definitions.writeln('struct $struct_name {')
|
|
|
|
|
g.definitions.writeln('\tint len;')
|
|
|
|
|
g.definitions.writeln('\t$type_name args[$arg_len];')
|
|
|
|
|
g.definitions.writeln('};\n')
|
|
|
|
|
g.type_definitions.writeln('struct $struct_name {')
|
|
|
|
|
g.type_definitions.writeln('\tint len;')
|
|
|
|
|
g.type_definitions.writeln('\t$type_name args[$arg_len];')
|
|
|
|
|
g.type_definitions.writeln('};\n')
|
|
|
|
|
g.typedefs.writeln('typedef struct $struct_name $struct_name;')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2223,26 +2261,26 @@ fn (g Gen) expr_is_multi_return_call(expr ast.Expr) bool {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
g.write('return ')
|
|
|
|
|
if g.fn_decl.name == 'main' {
|
|
|
|
|
g.writeln('0;')
|
|
|
|
|
g.writeln('return 0;')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// got to do a correct check for multireturn
|
|
|
|
|
sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
|
|
|
|
fn_return_is_multi := sym.kind == .multi_return
|
|
|
|
|
fn_return_is_optional := g.fn_decl.return_type.flag_is(.optional)
|
|
|
|
|
// handle none/error for optional
|
|
|
|
|
// handle promoting none/error/function returning 'Option'
|
|
|
|
|
if fn_return_is_optional {
|
|
|
|
|
optional_none := node.exprs[0] is ast.None
|
|
|
|
|
mut optional_error := false
|
|
|
|
|
match node.exprs[0] {
|
|
|
|
|
ast.CallExpr { optional_error = it.name == 'error' }
|
|
|
|
|
else { false }
|
|
|
|
|
}
|
|
|
|
|
if optional_none || optional_error {
|
|
|
|
|
mut is_regular_option := g.typ(node.types[0]) == 'Option'
|
|
|
|
|
if optional_none || is_regular_option {
|
|
|
|
|
tmp := g.new_tmp_var()
|
|
|
|
|
g.write('/*opt promotion*/ Option $tmp = ')
|
|
|
|
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
|
|
|
|
g.write(';')
|
|
|
|
|
|
|
|
|
|
styp := g.typ(g.fn_decl.return_type)
|
|
|
|
|
g.writeln('return *($styp*)&$tmp;')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2251,10 +2289,20 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
// typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
|
|
|
|
// mr_info := typ_sym.info as table.MultiReturn
|
|
|
|
|
mut styp := ''
|
|
|
|
|
|
|
|
|
|
mut opt_tmp := ''
|
|
|
|
|
mut opt_type := ''
|
|
|
|
|
|
|
|
|
|
if fn_return_is_optional {
|
|
|
|
|
opt_type = g.typ(g.fn_decl.return_type)
|
|
|
|
|
// Create a tmp for this option
|
|
|
|
|
opt_tmp = g.new_tmp_var()
|
|
|
|
|
g.write('$opt_type $opt_tmp;')
|
|
|
|
|
styp = g.base_type(g.fn_decl.return_type)
|
|
|
|
|
g.write('opt_ok(&($styp/*X*/[]) { ')
|
|
|
|
|
|
|
|
|
|
g.write('opt_ok2(&($styp/*X*/[]) { ')
|
|
|
|
|
} else {
|
|
|
|
|
g.write('return ')
|
|
|
|
|
styp = g.typ(g.fn_decl.return_type)
|
|
|
|
|
}
|
|
|
|
|
// Use this to keep the tmp assignments in order
|
|
|
|
@ -2275,6 +2323,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
g.writeln(';')
|
|
|
|
|
multi_unpack += g.go_before_stmt(0)
|
|
|
|
|
g.write(s)
|
|
|
|
|
|
|
|
|
|
expr_types := expr_sym.mr_info().types
|
|
|
|
|
for j, _ in expr_types {
|
|
|
|
|
g.write('.arg$arg_idx=${tmp}.arg$j')
|
|
|
|
@ -2294,7 +2343,8 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
}
|
|
|
|
|
g.write('}')
|
|
|
|
|
if fn_return_is_optional {
|
|
|
|
|
g.write(' }, sizeof($styp))')
|
|
|
|
|
g.writeln(' }, (OptionBase*)(&$opt_tmp), sizeof($styp));')
|
|
|
|
|
g.write('return $opt_tmp')
|
|
|
|
|
}
|
|
|
|
|
// Make sure to add our unpacks
|
|
|
|
|
g.insert_before_stmt(multi_unpack)
|
|
|
|
@ -2305,7 +2355,11 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
if fn_return_is_optional && !node.types[0].flag_is(.optional) && return_sym.name !=
|
|
|
|
|
'Option' {
|
|
|
|
|
styp := g.base_type(g.fn_decl.return_type)
|
|
|
|
|
g.write('/*$return_sym.name*/opt_ok(&($styp[]) { ')
|
|
|
|
|
opt_type := g.typ(g.fn_decl.return_type)
|
|
|
|
|
// Create a tmp for this option
|
|
|
|
|
opt_tmp := g.new_tmp_var()
|
|
|
|
|
g.write('$opt_type $opt_tmp;')
|
|
|
|
|
g.write('/*:)$return_sym.name*/opt_ok2(&($styp[]) { ')
|
|
|
|
|
if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
|
|
|
|
|
// Automatic Dereference for optional
|
|
|
|
|
g.write('*')
|
|
|
|
@ -2316,9 +2370,11 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
g.write(', ')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g.writeln(' }, sizeof($styp));')
|
|
|
|
|
g.writeln(' }, (OptionBase*)(&$opt_tmp), sizeof($styp));')
|
|
|
|
|
g.writeln('return $opt_tmp;')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.write('return ')
|
|
|
|
|
cast_interface := sym.kind == .interface_ && node.types[0] != g.fn_decl.return_type
|
|
|
|
|
if cast_interface {
|
|
|
|
|
g.interface_call(node.types[0], g.fn_decl.return_type)
|
|
|
|
@ -2327,6 +2383,8 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|
|
|
|
if cast_interface {
|
|
|
|
|
g.write(')')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
g.write('return')
|
|
|
|
|
}
|
|
|
|
|
g.writeln(';')
|
|
|
|
|
}
|
|
|
|
@ -2653,8 +2711,8 @@ fn (mut g Gen) write_sorted_types() {
|
|
|
|
|
// sort structs
|
|
|
|
|
types_sorted := g.sort_structs(types)
|
|
|
|
|
// Generate C code
|
|
|
|
|
g.definitions.writeln('// builtin types:')
|
|
|
|
|
g.definitions.writeln('//------------------ #endbuiltin')
|
|
|
|
|
g.type_definitions.writeln('// builtin types:')
|
|
|
|
|
g.type_definitions.writeln('//------------------ #endbuiltin')
|
|
|
|
|
g.write_types(types_sorted)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2668,39 +2726,59 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
|
|
|
|
match typ.info {
|
|
|
|
|
table.Struct {
|
|
|
|
|
info := typ.info as table.Struct
|
|
|
|
|
// g.definitions.writeln('typedef struct {')
|
|
|
|
|
// TODO avoid buffer manip
|
|
|
|
|
start_pos := g.type_definitions.len
|
|
|
|
|
if info.is_union {
|
|
|
|
|
g.definitions.writeln('union $name {')
|
|
|
|
|
g.type_definitions.writeln('union $name {')
|
|
|
|
|
} else {
|
|
|
|
|
g.definitions.writeln('struct $name {')
|
|
|
|
|
g.type_definitions.writeln('struct $name {')
|
|
|
|
|
}
|
|
|
|
|
if info.fields.len > 0 {
|
|
|
|
|
for field in info.fields {
|
|
|
|
|
// Some of these structs may want to contain
|
|
|
|
|
// optionals that may not be defined at this point
|
|
|
|
|
// if this is the case then we are going to
|
|
|
|
|
// buffer manip out in front of the struct
|
|
|
|
|
// write the optional in and then continue
|
|
|
|
|
if field.typ.flag_is(.optional) {
|
|
|
|
|
// Dont use g.typ() here becuase it will register
|
|
|
|
|
// optional and we dont want that
|
|
|
|
|
last_text := g.type_definitions.after(start_pos).clone()
|
|
|
|
|
g.type_definitions.go_back_to(start_pos)
|
|
|
|
|
styp, base := g.optional_type_name(field.typ)
|
|
|
|
|
g.optionals << styp
|
|
|
|
|
g.typedefs2.writeln('typedef struct $styp $styp;')
|
|
|
|
|
g.type_definitions.writeln('${g.optional_type_text(styp, base)};')
|
|
|
|
|
g.type_definitions.write(last_text)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type_name := g.typ(field.typ)
|
|
|
|
|
|
|
|
|
|
field_name := c_name(field.name)
|
|
|
|
|
g.definitions.writeln('\t$type_name $field_name;')
|
|
|
|
|
|
|
|
|
|
g.type_definitions.writeln('\t$type_name $field_name;')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
g.definitions.writeln('EMPTY_STRUCT_DECLARATION;')
|
|
|
|
|
g.type_definitions.writeln('EMPTY_STRUCT_DECLARATION;')
|
|
|
|
|
}
|
|
|
|
|
// g.definitions.writeln('} $name;\n')
|
|
|
|
|
// g.type_definitions.writeln('} $name;\n')
|
|
|
|
|
//
|
|
|
|
|
g.definitions.writeln('};\n')
|
|
|
|
|
g.type_definitions.writeln('};\n')
|
|
|
|
|
}
|
|
|
|
|
table.Alias {
|
|
|
|
|
// table.Alias, table.SumType { TODO
|
|
|
|
|
}
|
|
|
|
|
table.SumType {
|
|
|
|
|
g.definitions.writeln('')
|
|
|
|
|
g.definitions.writeln('// Sum type $name = ')
|
|
|
|
|
g.type_definitions.writeln('')
|
|
|
|
|
g.type_definitions.writeln('// Sum type $name = ')
|
|
|
|
|
for sv in it.variants {
|
|
|
|
|
g.definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
|
|
|
|
|
g.type_definitions.writeln('// | ${sv:4d} = ${g.typ(sv):-20s}')
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('typedef struct {')
|
|
|
|
|
g.definitions.writeln(' void* obj;')
|
|
|
|
|
g.definitions.writeln(' int typ;')
|
|
|
|
|
g.definitions.writeln('} $name;')
|
|
|
|
|
g.definitions.writeln('')
|
|
|
|
|
g.type_definitions.writeln('typedef struct {')
|
|
|
|
|
g.type_definitions.writeln(' void* obj;')
|
|
|
|
|
g.type_definitions.writeln(' int typ;')
|
|
|
|
|
g.type_definitions.writeln('} $name;')
|
|
|
|
|
g.type_definitions.writeln('')
|
|
|
|
|
}
|
|
|
|
|
table.ArrayFixed {
|
|
|
|
|
// .array_fixed {
|
|
|
|
@ -2712,7 +2790,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
|
|
|
|
if fixed.starts_with('C__') {
|
|
|
|
|
fixed = fixed[3..]
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('typedef $fixed $styp [$len];')
|
|
|
|
|
g.type_definitions.writeln('typedef $fixed $styp [$len];')
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
else {}
|
|
|
|
@ -2987,8 +3065,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if g.typ(node.expr_types[i]).starts_with('Option') {
|
|
|
|
|
str_fn_name := 'Option_str'
|
|
|
|
|
g.write('${str_fn_name}(*(Option*)&')
|
|
|
|
|
str_fn_name := 'OptionBase_str'
|
|
|
|
|
g.write('${str_fn_name}(*(OptionBase*)&')
|
|
|
|
|
g.expr(expr)
|
|
|
|
|
g.write(')')
|
|
|
|
|
} else {
|
|
|
|
@ -3166,7 +3244,9 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
|
|
|
|
g.writeln('\tv_panic(${cvar_name}.v_error);')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
g.writeln('\treturn $cvar_name;')
|
|
|
|
|
// Now that option types are distinct we need a cast here
|
|
|
|
|
styp := g.typ(g.fn_decl.return_type)
|
|
|
|
|
g.writeln('\treturn *($styp *)&$cvar_name;')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g.write('}')
|
|
|
|
@ -3560,17 +3640,17 @@ fn (mut g Gen) go_stmt(node ast.GoStmt) {
|
|
|
|
|
if name in g.threaded_fns {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('\ntypedef struct $wrapper_struct_name {')
|
|
|
|
|
g.type_definitions.writeln('\ntypedef struct $wrapper_struct_name {')
|
|
|
|
|
if it.is_method {
|
|
|
|
|
styp := g.typ(it.receiver_type)
|
|
|
|
|
g.definitions.writeln('\t$styp arg0;')
|
|
|
|
|
g.type_definitions.writeln('\t$styp arg0;')
|
|
|
|
|
}
|
|
|
|
|
for i, arg in it.args {
|
|
|
|
|
styp := g.typ(arg.typ)
|
|
|
|
|
g.definitions.writeln('\t$styp arg${i+1};')
|
|
|
|
|
g.type_definitions.writeln('\t$styp arg${i+1};')
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('} $wrapper_struct_name;')
|
|
|
|
|
g.definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg);')
|
|
|
|
|
g.type_definitions.writeln('} $wrapper_struct_name;')
|
|
|
|
|
g.type_definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg);')
|
|
|
|
|
g.gowrappers.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg) {')
|
|
|
|
|
g.gowrappers.write('\t${name}(')
|
|
|
|
|
if it.is_method {
|
|
|
|
@ -3667,7 +3747,7 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
|
|
|
|
already_generated_key_no_ptr := '${styp}:${str_fn_name_no_ptr}'
|
|
|
|
|
if already_generated_key_no_ptr !in g.str_types {
|
|
|
|
|
g.str_types << already_generated_key_no_ptr
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name_no_ptr}(${styp} it); // auto no_ptr version')
|
|
|
|
|
g.type_definitions.writeln('string ${str_fn_name_no_ptr}(${styp} it); // auto no_ptr version')
|
|
|
|
|
g.auto_str_funcs.writeln('string ${str_fn_name_no_ptr}(${styp} it){ return ${str_fn_name}(&it); }')
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
@ -3724,7 +3804,7 @@ fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp, str_fn_name string) {
|
|
|
|
|
} else {
|
|
|
|
|
verror("could not generate string method for type \'${styp}\'")
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
|
|
|
|
g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
|
|
|
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) {')
|
|
|
|
|
if convertor == 'bool' {
|
|
|
|
|
g.auto_str_funcs.writeln('\tstring tmp1 = string_add(tos_lit("${styp}("), (${convertor})it ? tos_lit("true") : tos_lit("false"));')
|
|
|
|
@ -3739,7 +3819,7 @@ fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp, str_fn_name string) {
|
|
|
|
|
|
|
|
|
|
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
|
|
|
|
s := styp.replace('.', '__')
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
|
|
|
|
g.type_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('\tswitch(it) {')
|
|
|
|
|
for val in info.vals {
|
|
|
|
@ -3764,7 +3844,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
|
|
|
|
fnames2strfunc[field_styp] = field_fn_name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp x, int indent_count); // auto')
|
|
|
|
|
g.type_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) {')
|
|
|
|
|
mut clean_struct_v_type_name := styp.replace('__', '.')
|
|
|
|
|
if styp.ends_with('*') {
|
|
|
|
@ -3841,7 +3921,7 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp, str_fn_name string) {
|
|
|
|
|
// eprintln('> sym.name: does not have method `str`')
|
|
|
|
|
g.gen_str_for_type_with_styp(info.elem_type, field_styp)
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp a); // auto')
|
|
|
|
|
g.type_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('\tstrings__Builder sb = strings__new_builder(a.len * 10);')
|
|
|
|
|
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos_lit("["));')
|
|
|
|
@ -3902,7 +3982,7 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp, str_fn_name
|
|
|
|
|
if !sym.has_method('str') {
|
|
|
|
|
g.gen_str_for_type_with_styp(info.elem_type, field_styp)
|
|
|
|
|
}
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp a); // auto')
|
|
|
|
|
g.type_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('\tstrings__Builder sb = strings__new_builder($info.size * 10);')
|
|
|
|
|
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos_lit("["));')
|
|
|
|
@ -3944,7 +4024,7 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp, str_fn_name string) {
|
|
|
|
|
g.gen_str_for_type_with_styp(info.value_type, val_styp)
|
|
|
|
|
}
|
|
|
|
|
zero := g.type_default(info.value_type)
|
|
|
|
|
g.definitions.writeln('string ${str_fn_name}($styp m); // auto')
|
|
|
|
|
g.type_definitions.writeln('string ${str_fn_name}($styp m); // auto')
|
|
|
|
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp m) { /* gen_str_for_map */')
|
|
|
|
|
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(m.key_values.size*10);')
|
|
|
|
|
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos_lit("{"));')
|
|
|
|
|