compiler: fix struct order bug
							parent
							
								
									f29079daac
								
							
						
					
					
						commit
						5b1700e52a
					
				| 
						 | 
					@ -6,6 +6,7 @@ module main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import strings
 | 
					import strings
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CGen {
 | 
					struct CGen {
 | 
				
			||||||
	out          os.File
 | 
						out          os.File
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ struct CGen {
 | 
				
			||||||
	typedefs     []string
 | 
						typedefs     []string
 | 
				
			||||||
	type_aliases []string
 | 
						type_aliases []string
 | 
				
			||||||
	includes     []string
 | 
						includes     []string
 | 
				
			||||||
	types        []string
 | 
						//types        []string
 | 
				
			||||||
	thread_args  []string
 | 
						thread_args  []string
 | 
				
			||||||
	thread_fns   []string
 | 
						thread_fns   []string
 | 
				
			||||||
	consts       []string
 | 
						consts       []string
 | 
				
			||||||
| 
						 | 
					@ -216,12 +217,14 @@ fn (p mut Parser) print_prof_counters() string {
 | 
				
			||||||
	return res.join(';\n')
 | 
						return res.join(';\n')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
fn (p mut Parser) gen_type(s string) {
 | 
					fn (p mut Parser) gen_type(s string) {
 | 
				
			||||||
	if !p.first_pass() {
 | 
						if !p.first_pass() {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p.cgen.types << s
 | 
						p.cgen.types << s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (p mut Parser) gen_typedef(s string) {
 | 
					fn (p mut Parser) gen_typedef(s string) {
 | 
				
			||||||
	if !p.first_pass() {
 | 
						if !p.first_pass() {
 | 
				
			||||||
| 
						 | 
					@ -290,3 +293,45 @@ fn platform_postfix_to_ifdefguard(name string) string {
 | 
				
			||||||
  panic('bad platform_postfix "$name"')
 | 
					  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'))) {
 | 
						(v.pref.build_mode == .build && v.dir.contains('/ui'))) {
 | 
				
			||||||
		cgen.genln('id defaultFont = 0; // main.v')
 | 
							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
 | 
						// We need the cjson header for all the json decoding user will do in default mode
 | 
				
			||||||
	if v.pref.build_mode == .default_mode {
 | 
						if v.pref.build_mode == .default_mode {
 | 
				
			||||||
		if imports_json {
 | 
							if imports_json {
 | 
				
			||||||
| 
						 | 
					@ -300,7 +294,8 @@ fn (v mut V) compile() {
 | 
				
			||||||
	mut d := strings.new_builder(10000)// Avoid unnecessary allocations
 | 
						mut d := strings.new_builder(10000)// Avoid unnecessary allocations
 | 
				
			||||||
	d.writeln(cgen.includes.join_lines())
 | 
						d.writeln(cgen.includes.join_lines())
 | 
				
			||||||
	d.writeln(cgen.typedefs.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(const char*, ...);\n')
 | 
				
			||||||
	d.writeln('\nstring _STR_TMP(const char*, ...);\n')
 | 
						d.writeln('\nstring _STR_TMP(const char*, ...);\n')
 | 
				
			||||||
	d.writeln(cgen.fns.join_lines())
 | 
						d.writeln(cgen.fns.join_lines())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -491,8 +491,8 @@ fn key_to_type_cat(tok Token) TypeCategory {
 | 
				
			||||||
fn (p mut Parser) struct_decl() {
 | 
					fn (p mut Parser) struct_decl() {
 | 
				
			||||||
	// V can generate Objective C for integration with Cocoa
 | 
						// V can generate Objective C for integration with Cocoa
 | 
				
			||||||
	// `[interface:ParentInterface]`
 | 
						// `[interface:ParentInterface]`
 | 
				
			||||||
	is_objc := p.attr.starts_with('interface')
 | 
						//is_objc := p.attr.starts_with('interface')
 | 
				
			||||||
	objc_parent := if is_objc { p.attr.right(10) } else { '' }
 | 
						//objc_parent := if is_objc { p.attr.right(10) } else { '' }
 | 
				
			||||||
	// interface, union, struct
 | 
						// interface, union, struct
 | 
				
			||||||
	is_interface := p.tok == .key_interface
 | 
						is_interface := p.tok == .key_interface
 | 
				
			||||||
	is_union := p.tok == .key_union
 | 
						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) {
 | 
						if p.pass == .decl && p.table.known_type(name) {
 | 
				
			||||||
		p.error('`$name` redeclared')
 | 
							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 {
 | 
						if !is_c {
 | 
				
			||||||
		kind := if is_union {'union'} else {'struct'}
 | 
							kind := if is_union {'union'} else {'struct'}
 | 
				
			||||||
		p.gen_typedef('typedef $kind $name $name;')
 | 
							p.gen_typedef('typedef $kind $name $name;')
 | 
				
			||||||
			p.gen_type('$kind $name {')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Register the type
 | 
						// Register the type
 | 
				
			||||||
	mut typ := p.table.find_type(name)
 | 
						mut typ := p.table.find_type(name)
 | 
				
			||||||
| 
						 | 
					@ -634,10 +626,6 @@ fn (p mut Parser) struct_decl() {
 | 
				
			||||||
		is_atomic := p.tok == .key_atomic
 | 
							is_atomic := p.tok == .key_atomic
 | 
				
			||||||
		if is_atomic {
 | 
							if is_atomic {
 | 
				
			||||||
			p.next()
 | 
								p.next()
 | 
				
			||||||
			p.gen_type('_Atomic ')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !is_c {
 | 
					 | 
				
			||||||
			p.gen_type(p.table.cgen_name_type_pair(field_name, field_type) + ';')
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// [ATTR]
 | 
							// [ATTR]
 | 
				
			||||||
		mut attr := ''
 | 
							mut attr := ''
 | 
				
			||||||
| 
						 | 
					@ -665,17 +653,6 @@ fn (p mut Parser) struct_decl() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p.check(.rcbr)
 | 
						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')
 | 
						p.fgenln('\n')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,7 @@ enum AccessMod {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum TypeCategory {
 | 
					enum TypeCategory {
 | 
				
			||||||
 | 
						builtin
 | 
				
			||||||
	struct_
 | 
						struct_
 | 
				
			||||||
	func
 | 
						func
 | 
				
			||||||
	interface_ // 2
 | 
						interface_ // 2
 | 
				
			||||||
| 
						 | 
					@ -901,3 +902,12 @@ fn (fit &FileImportTable) is_aliased(mod string) bool {
 | 
				
			||||||
fn (fit &FileImportTable) resolve_alias(alias string) string {
 | 
					fn (fit &FileImportTable) resolve_alias(alias string) string {
 | 
				
			||||||
	return fit.imports[alias]
 | 
						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