compiler: fix struct order bug
parent
f29079daac
commit
5b1700e52a
|
@ -6,6 +6,7 @@ module main
|
|||
|
||||
import os
|
||||
import strings
|
||||
import time
|
||||
|
||||
struct CGen {
|
||||
out os.File
|
||||
|
@ -13,7 +14,7 @@ struct CGen {
|
|||
typedefs []string
|
||||
type_aliases []string
|
||||
includes []string
|
||||
types []string
|
||||
//types []string
|
||||
thread_args []string
|
||||
thread_fns []string
|
||||
consts []string
|
||||
|
@ -216,12 +217,14 @@ fn (p mut Parser) print_prof_counters() string {
|
|||
return res.join(';\n')
|
||||
}
|
||||
|
||||
/*
|
||||
fn (p mut Parser) gen_type(s string) {
|
||||
if !p.first_pass() {
|
||||
return
|
||||
}
|
||||
p.cgen.types << s
|
||||
}
|
||||
*/
|
||||
|
||||
fn (p mut Parser) gen_typedef(s string) {
|
||||
if !p.first_pass() {
|
||||
|
@ -290,3 +293,45 @@ fn platform_postfix_to_ifdefguard(name string) string {
|
|||
panic('bad platform_postfix "$name"')
|
||||
}
|
||||
|
||||
// C struct definitions, ordered
|
||||
fn (v mut V) c_type_definitions() string {
|
||||
mut types := v.table.types
|
||||
// Sort the types, make sure types that are referenced by other types
|
||||
// are added before them.
|
||||
for i in 0 .. types.len {
|
||||
for j in 0 .. i {
|
||||
t := types[i]
|
||||
if types[j].contains_field_type(t.name) {
|
||||
types[i] = types[j]
|
||||
types[j] = t
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// Generate C code
|
||||
mut sb := strings.new_builder(10)
|
||||
for t in v.table.types {
|
||||
if t.cat != .union_ && t.cat != .struct_ {
|
||||
continue
|
||||
}
|
||||
//if is_objc {
|
||||
//sb.writeln('@interface $name : $objc_parent { @public')
|
||||
//}
|
||||
//if is_atomic {
|
||||
//sb.write('_Atomic ')
|
||||
//}
|
||||
kind := if t.cat == .union_ {'union'} else {'struct'}
|
||||
sb.writeln('$kind $t.name {')
|
||||
for field in t.fields {
|
||||
sb.writeln(v.table.cgen_name_type_pair(field.name,
|
||||
field.typ) + ';')
|
||||
}
|
||||
sb.writeln('};\n')
|
||||
//if is_objc {
|
||||
//p.gen_type('@end')
|
||||
//}
|
||||
}
|
||||
return sb.str()
|
||||
}
|
||||
|
||||
|
|
|
@ -256,12 +256,6 @@ fn (v mut V) compile() {
|
|||
(v.pref.build_mode == .build && v.dir.contains('/ui'))) {
|
||||
cgen.genln('id defaultFont = 0; // main.v')
|
||||
}
|
||||
// TODO remove ugly .c include once V has its own json parser
|
||||
// Embed cjson either in embedvlib or in json.o
|
||||
if (imports_json && v.pref.build_mode == .embed_vlib) ||
|
||||
(v.pref.build_mode == .build && v.out_name.contains('json.o')) {
|
||||
//cgen.genln('#include "cJSON.c" ')
|
||||
}
|
||||
// We need the cjson header for all the json decoding user will do in default mode
|
||||
if v.pref.build_mode == .default_mode {
|
||||
if imports_json {
|
||||
|
@ -300,7 +294,8 @@ fn (v mut V) compile() {
|
|||
mut d := strings.new_builder(10000)// Avoid unnecessary allocations
|
||||
d.writeln(cgen.includes.join_lines())
|
||||
d.writeln(cgen.typedefs.join_lines())
|
||||
d.writeln(cgen.types.join_lines())
|
||||
//d.writeln(cgen.types.join_lines())
|
||||
d.writeln(v.c_type_definitions())
|
||||
d.writeln('\nstring _STR(const char*, ...);\n')
|
||||
d.writeln('\nstring _STR_TMP(const char*, ...);\n')
|
||||
d.writeln(cgen.fns.join_lines())
|
||||
|
|
|
@ -491,8 +491,8 @@ fn key_to_type_cat(tok Token) TypeCategory {
|
|||
fn (p mut Parser) struct_decl() {
|
||||
// V can generate Objective C for integration with Cocoa
|
||||
// `[interface:ParentInterface]`
|
||||
is_objc := p.attr.starts_with('interface')
|
||||
objc_parent := if is_objc { p.attr.right(10) } else { '' }
|
||||
//is_objc := p.attr.starts_with('interface')
|
||||
//objc_parent := if is_objc { p.attr.right(10) } else { '' }
|
||||
// interface, union, struct
|
||||
is_interface := p.tok == .key_interface
|
||||
is_union := p.tok == .key_union
|
||||
|
@ -527,17 +527,9 @@ fn (p mut Parser) struct_decl() {
|
|||
if p.pass == .decl && p.table.known_type(name) {
|
||||
p.error('`$name` redeclared')
|
||||
}
|
||||
// Generate type definitions
|
||||
if is_objc {
|
||||
p.gen_type('@interface $name : $objc_parent { @public')
|
||||
}
|
||||
else {
|
||||
// type alias is generated later
|
||||
if !is_c {
|
||||
kind := if is_union {'union'} else {'struct'}
|
||||
p.gen_typedef('typedef $kind $name $name;')
|
||||
p.gen_type('$kind $name {')
|
||||
}
|
||||
}
|
||||
// Register the type
|
||||
mut typ := p.table.find_type(name)
|
||||
|
@ -634,10 +626,6 @@ fn (p mut Parser) struct_decl() {
|
|||
is_atomic := p.tok == .key_atomic
|
||||
if is_atomic {
|
||||
p.next()
|
||||
p.gen_type('_Atomic ')
|
||||
}
|
||||
if !is_c {
|
||||
p.gen_type(p.table.cgen_name_type_pair(field_name, field_type) + ';')
|
||||
}
|
||||
// [ATTR]
|
||||
mut attr := ''
|
||||
|
@ -665,17 +653,6 @@ fn (p mut Parser) struct_decl() {
|
|||
}
|
||||
|
||||
p.check(.rcbr)
|
||||
if !is_c {
|
||||
if !did_gen_something {
|
||||
p.gen_type('EMPTY_STRUCT_DECLARATION };')
|
||||
p.fgenln('')
|
||||
} else {
|
||||
p.gen_type('}; ')
|
||||
}
|
||||
}
|
||||
if is_objc {
|
||||
p.gen_type('@end')
|
||||
}
|
||||
p.fgenln('\n')
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ enum AccessMod {
|
|||
}
|
||||
|
||||
enum TypeCategory {
|
||||
builtin
|
||||
struct_
|
||||
func
|
||||
interface_ // 2
|
||||
|
@ -901,3 +902,12 @@ fn (fit &FileImportTable) is_aliased(mod string) bool {
|
|||
fn (fit &FileImportTable) resolve_alias(alias string) string {
|
||||
return fit.imports[alias]
|
||||
}
|
||||
|
||||
fn (t &Type) contains_field_type(typ string) bool {
|
||||
for field in t.fields {
|
||||
if field.typ == typ {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue