mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
run vfmt on vlib/builtin
This commit is contained in:
@ -3,8 +3,6 @@
|
||||
// that can be found in the LICENSE file.
|
||||
module compiler
|
||||
|
||||
|
||||
|
||||
import (
|
||||
strings
|
||||
)
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
module compiler
|
||||
|
||||
import strings
|
||||
@ -9,15 +8,16 @@ import strings
|
||||
const (
|
||||
dot_ptr = '->'
|
||||
)
|
||||
|
||||
// returns the type of the new variable
|
||||
fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
|
||||
p.is_var_decl = true
|
||||
mut typ := p.bool_expression()
|
||||
//mut typ, expr := p.tmp_expr()
|
||||
// mut typ, expr := p.tmp_expr()
|
||||
p.is_var_decl = false
|
||||
if typ.starts_with('...') { typ = typ[3..] }
|
||||
//p.gen('/*after expr*/')
|
||||
if typ.starts_with('...') {
|
||||
typ = typ[3..]
|
||||
}
|
||||
// p.gen('/*after expr*/')
|
||||
// Option check ? or {
|
||||
or_else := p.tok == .key_orelse
|
||||
if or_else {
|
||||
@ -26,39 +26,34 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
|
||||
gen_name := p.table.var_cgen_name(name)
|
||||
mut nt_gen := p.table.cgen_name_type_pair(gen_name, typ)
|
||||
// `foo := C.Foo{}` => `Foo foo;`
|
||||
if !p.is_empty_c_struct_init && !typ.starts_with('['){
|
||||
if !p.is_empty_c_struct_init && !typ.starts_with('[') {
|
||||
nt_gen += '='
|
||||
} else if typ.starts_with('[') && typ[ typ.len-1 ] != `*` {
|
||||
}
|
||||
else if typ.starts_with('[') && typ[typ.len - 1] != `*` {
|
||||
// a fixed_array initializer, like `v := [1.1, 2.2]!!`
|
||||
// ... should translate to the following in C `f32 v[2] = {1.1, 2.2};`
|
||||
initializer := p.cgen.cur_line
|
||||
if initializer.len > 0 {
|
||||
p.cgen.resetln(' = {' + initializer.all_after('{') )
|
||||
} else if initializer.len == 0 {
|
||||
p.cgen.resetln(' = {' + initializer.all_after('{'))
|
||||
}
|
||||
else if initializer.len == 0 {
|
||||
p.cgen.resetln(' = { 0 }')
|
||||
}
|
||||
}
|
||||
|
||||
if is_static {
|
||||
nt_gen = 'static $nt_gen'
|
||||
}
|
||||
// Now that we know the type, prepend it
|
||||
// `[typ] [name] = bool_expression();`
|
||||
//p.cgen.prepend_to_statement(nt_gen)
|
||||
// p.cgen.prepend_to_statement(nt_gen)
|
||||
p.cgen.set_placeholder(0, nt_gen)
|
||||
return typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_fn_decl(f Fn, typ, str_args string) {
|
||||
dll_export_linkage := if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so {
|
||||
'__declspec(dllexport) '
|
||||
} else if p.attr == 'inline' {
|
||||
'static inline '
|
||||
} else {
|
||||
''
|
||||
}
|
||||
dll_export_linkage := if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so { '__declspec(dllexport) ' } else if p.attr == 'inline' { 'static inline ' } else { '' }
|
||||
fn_name_cgen := p.table.fn_gen_name(f)
|
||||
//str_args := f.str_args(p.table)
|
||||
// str_args := f.str_args(p.table)
|
||||
p.genln('$dll_export_linkage$typ $fn_name_cgen ($str_args) {')
|
||||
}
|
||||
|
||||
@ -68,12 +63,12 @@ fn (p mut Parser) gen_blank_identifier_assign() {
|
||||
p.check_name()
|
||||
p.check_space(.assign)
|
||||
is_indexer := p.peek() == .lsbr
|
||||
is_fn_call, next_expr := p.is_expr_fn_call(p.token_idx)
|
||||
is_fn_call,next_expr := p.is_expr_fn_call(p.token_idx)
|
||||
pos := p.cgen.add_placeholder()
|
||||
p.is_var_decl = true
|
||||
typ := p.bool_expression()
|
||||
if typ == 'void' {
|
||||
p.error_with_token_index('${next_expr}() $err_used_as_value', p.token_idx-2)
|
||||
p.error_with_token_index('${next_expr}() $err_used_as_value', p.token_idx - 2)
|
||||
}
|
||||
p.is_var_decl = false
|
||||
if !is_indexer && !is_fn_call {
|
||||
@ -82,10 +77,12 @@ fn (p mut Parser) gen_blank_identifier_assign() {
|
||||
// handle or
|
||||
if p.tok == .key_orelse {
|
||||
p.gen_handle_option_or_else(typ, '', pos)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if is_fn_call {
|
||||
p.gen(';')
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.cgen.resetln('{$typ _ = $p.cgen.cur_line;}')
|
||||
}
|
||||
}
|
||||
@ -104,19 +101,20 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
|
||||
or_tok_idx := p.token_idx
|
||||
p.check(.key_orelse)
|
||||
p.check(.lcbr)
|
||||
p.register_var(Var {
|
||||
p.register_var(Var{
|
||||
name: 'err'
|
||||
typ: 'string'
|
||||
is_mut: false
|
||||
is_used: true
|
||||
})
|
||||
p.register_var(Var {
|
||||
p.register_var(Var{
|
||||
name: 'errcode'
|
||||
typ: 'int'
|
||||
is_mut: false
|
||||
is_used: true
|
||||
})
|
||||
if is_assign && !name.contains('.') { // don't initialize struct fields
|
||||
if is_assign && !name.contains('.') {
|
||||
// don't initialize struct fields
|
||||
p.genln('$typ $name;')
|
||||
}
|
||||
p.genln('if (!$tmp .ok) {')
|
||||
@ -128,23 +126,20 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
|
||||
// workaround for -g with default optional value
|
||||
// when p.cgen.line_directives is true an extra
|
||||
// line is added so we need to account for that
|
||||
expr_line := if p.cgen.line_directives {
|
||||
p.cgen.lines[p.cgen.lines.len-3]
|
||||
} else {
|
||||
p.cgen.lines[p.cgen.lines.len-2]
|
||||
}
|
||||
expr_line := if p.cgen.line_directives { p.cgen.lines[p.cgen.lines.len - 3] } else { p.cgen.lines[p.cgen.lines.len - 2] }
|
||||
last_expr := expr_line[last_ph..]
|
||||
p.cgen.lines[p.cgen.lines.len-2] = ''
|
||||
p.cgen.lines[p.cgen.lines.len - 2] = ''
|
||||
// same here
|
||||
if p.cgen.line_directives {
|
||||
p.cgen.lines[p.cgen.lines.len-3] = ''
|
||||
p.cgen.lines[p.cgen.lines.len - 3] = ''
|
||||
}
|
||||
p.genln('if ($tmp .ok) {')
|
||||
p.genln('$name = *($typ*) $tmp . data;')
|
||||
p.genln('} else {')
|
||||
p.genln('$name = $last_expr')
|
||||
p.genln('}')
|
||||
} else if is_assign {
|
||||
}
|
||||
else if is_assign {
|
||||
p.genln('$name = *($typ*)${tmp}.data;')
|
||||
}
|
||||
if !p.returns && last_typ != typ && is_assign && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break {
|
||||
@ -172,18 +167,18 @@ fn (p mut Parser) gen_handle_question_suffix(f Fn, ph int) string {
|
||||
fn types_to_c(types []Type, table &Table) string {
|
||||
mut sb := strings.new_builder(10)
|
||||
for t in types {
|
||||
//if t.cat != .union_ && t.cat != .struct_ && t.cat != .objc_interface {
|
||||
// if t.cat != .union_ && t.cat != .struct_ && t.cat != .objc_interface {
|
||||
if !(t.cat in [.union_, .struct_, .objc_interface, .interface_]) {
|
||||
continue
|
||||
}
|
||||
//if is_atomic {
|
||||
//sb.write('_Atomic ')
|
||||
//}
|
||||
// if is_atomic {
|
||||
// sb.write('_Atomic ')
|
||||
// }
|
||||
if t.cat == .objc_interface {
|
||||
sb.writeln('@interface $t.name : $t.parent { @public')
|
||||
}
|
||||
else {
|
||||
kind := if t.cat == .union_ {'union'} else {'struct'}
|
||||
kind := if t.cat == .union_ { 'union' } else { 'struct' }
|
||||
sb.writeln('$kind $t.name {')
|
||||
if t.cat == .interface_ {
|
||||
sb.writeln('\tvoid* _object;')
|
||||
@ -192,11 +187,10 @@ fn types_to_c(types []Type, table &Table) string {
|
||||
}
|
||||
for field in t.fields {
|
||||
sb.write('\t')
|
||||
sb.writeln(table.cgen_name_type_pair(field.name,
|
||||
field.typ) + ';')
|
||||
sb.writeln(table.cgen_name_type_pair(field.name, field.typ) + ';')
|
||||
}
|
||||
sb.writeln('};\n')
|
||||
if t.cat == .objc_interface {
|
||||
if t.cat == .objc_interface {
|
||||
sb.writeln('@end')
|
||||
}
|
||||
}
|
||||
@ -211,7 +205,8 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
|
||||
if p.cgen.is_tmp {
|
||||
index_expr = p.cgen.tmp_line[fn_ph..]
|
||||
p.cgen.resetln(p.cgen.tmp_line[..fn_ph])
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
index_expr = p.cgen.cur_line[fn_ph..]
|
||||
p.cgen.resetln(p.cgen.cur_line[..fn_ph])
|
||||
}
|
||||
@ -221,8 +216,7 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
|
||||
if cfg.is_map {
|
||||
p.gen('$tmp')
|
||||
def := type_default(typ)
|
||||
p.cgen.insert_before('$typ $tmp = $def; ' +
|
||||
'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
|
||||
p.cgen.insert_before('$typ $tmp = $def; ' + 'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
|
||||
}
|
||||
else if cfg.is_arr {
|
||||
if p.pref.translated && !p.builtin_mod {
|
||||
@ -239,12 +233,13 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
|
||||
}
|
||||
}
|
||||
else if cfg.is_str && !p.builtin_mod {
|
||||
if p.pref.is_bare {
|
||||
if p.pref.is_bare {
|
||||
p.gen(index_expr)
|
||||
}
|
||||
else if cfg.is_slice {
|
||||
p.gen('string_substr2($index_expr)')
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.gen('string_at($index_expr)')
|
||||
}
|
||||
}
|
||||
@ -255,7 +250,6 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
|
||||
// p.cgen.insert_before('if (!${tmp}.str) $tmp = tos("", 0);')
|
||||
p.cgen.insert_before('if (!$tmp_ok) $tmp = tos((byte *)"", 0);')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
@ -265,18 +259,28 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
name = name.replace(' ', '')
|
||||
if f.name.len == 1 {
|
||||
match f.name[0] {
|
||||
`+` { name = name.replace('+', 'op_plus') }
|
||||
`-` { name = name.replace('-', 'op_minus') }
|
||||
`*` { name = name.replace('*', 'op_mul') }
|
||||
`/` { name = name.replace('/', 'op_div') }
|
||||
`%` { name = name.replace('%', 'op_mod') }
|
||||
else {}
|
||||
}
|
||||
`+` {
|
||||
name = name.replace('+', 'op_plus')
|
||||
}
|
||||
`-` {
|
||||
name = name.replace('-', 'op_minus')
|
||||
}
|
||||
`*` {
|
||||
name = name.replace('*', 'op_mul')
|
||||
}
|
||||
`/` {
|
||||
name = name.replace('/', 'op_div')
|
||||
}
|
||||
`%` {
|
||||
name = name.replace('%', 'op_mod')
|
||||
}
|
||||
else {
|
||||
}}
|
||||
}
|
||||
}
|
||||
if f.is_interface {
|
||||
// iname := f.args[0].typ // Speaker
|
||||
// var := p.expr_var.name
|
||||
// iname := f.args[0].typ // Speaker
|
||||
// var := p.expr_var.name
|
||||
return ''
|
||||
}
|
||||
// Avoid name conflicts (with things like abs(), print() etc).
|
||||
@ -288,20 +292,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
// Obfuscate but skip certain names
|
||||
// TODO ugly, fix
|
||||
// NB: the order here is from faster to potentially slower checks
|
||||
if table.obfuscate &&
|
||||
!f.is_c &&
|
||||
f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' &&
|
||||
f.name != 'gg__vec2' &&
|
||||
f.name != 'build_token_str' &&
|
||||
f.name != 'build_keys' &&
|
||||
f.mod != 'builtin' &&
|
||||
f.mod != 'darwin' &&
|
||||
f.mod != 'os' &&
|
||||
f.mod != 'json' &&
|
||||
!f.name.ends_with('_init') &&
|
||||
!f.name.contains('window_proc') &&
|
||||
!name.ends_with('_str') &&
|
||||
!name.contains('contains') {
|
||||
if table.obfuscate && !f.is_c && f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' && f.name != 'gg__vec2' && f.name != 'build_token_str' && f.name != 'build_keys' && f.mod != 'builtin' && f.mod != 'darwin' && f.mod != 'os' && f.mod != 'json' && !f.name.ends_with('_init') && !f.name.contains('window_proc') && !name.ends_with('_str') && !name.contains('contains') {
|
||||
mut idx := table.obf_ids[name]
|
||||
// No such function yet, register it
|
||||
if idx == 0 {
|
||||
@ -316,10 +307,8 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
|
||||
return name
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string,
|
||||
cgen_name string, ftyp string, method_ph int)
|
||||
{
|
||||
//mut cgen_name := p.table.fn_gen_name(f)
|
||||
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string, cgen_name string, ftyp string, method_ph int) {
|
||||
// mut cgen_name := p.table.fn_gen_name(f)
|
||||
mut method_call := cgen_name + ' ('
|
||||
// if receiver is key_mut or a ref (&), generate & for the first arg
|
||||
if receiver.ref || (receiver.is_mut && !receiver_type.contains('*')) {
|
||||
@ -337,7 +326,8 @@ fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string,
|
||||
// array_int => int
|
||||
cast = receiver_type.all_after('array_')
|
||||
cast = '*($cast*) '
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
cast = '(voidptr) '
|
||||
}
|
||||
}
|
||||
@ -346,12 +336,12 @@ fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string,
|
||||
|
||||
fn (p mut Parser) gen_array_at(typ_ string, is_arr0 bool, fn_ph int) {
|
||||
mut typ := typ_
|
||||
//p.fgen('[')
|
||||
// p.fgen('[')
|
||||
// array_int a; a[0]
|
||||
// type is "array_int", need "int"
|
||||
// typ = typ.replace('array_', '')
|
||||
// if is_arr0 {
|
||||
// typ = typ.right(6)
|
||||
// typ = typ.right(6)
|
||||
// }
|
||||
// array a; a.first() voidptr
|
||||
// type is "array", need "void*"
|
||||
@ -372,28 +362,36 @@ fn (p mut Parser) gen_array_at(typ_ string, is_arr0 bool, fn_ph int) {
|
||||
|
||||
fn (p mut Parser) gen_for_header(i, tmp, var_typ, val string) {
|
||||
p.genln('for (int $i = 0; $i < ${tmp}.len; $i++) {')
|
||||
if val == '_' { return }
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
p.genln('$var_typ $val = (($var_typ *) $tmp . data)[$i];')
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_for_fixed_header(i, tmp, var_typ, val string) {
|
||||
p.genln('for (int $i = 0; $i < sizeof(${tmp}) / sizeof($tmp [0]); $i++) {')
|
||||
if val == '_' { return }
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
p.genln('$var_typ $val = $tmp[$i];')
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_for_str_header(i, tmp, var_typ, val string) {
|
||||
// TODO var_typ is always byte
|
||||
//p.genln('array_byte bytes_$tmp = string_bytes( $tmp );')
|
||||
// p.genln('array_byte bytes_$tmp = string_bytes( $tmp );')
|
||||
p.genln(';\nfor (int $i = 0; $i < $tmp .len; $i ++) {')
|
||||
if val == '_' { return }
|
||||
//p.genln('$var_typ $val = (($var_typ *) bytes_$tmp . data)[$i];')
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
// p.genln('$var_typ $val = (($var_typ *) bytes_$tmp . data)[$i];')
|
||||
p.genln('$var_typ $val = ${tmp}.str[$i];')
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_for_range_header(i, range_end, tmp, var_type, val string) {
|
||||
p.genln(';\nfor (int $i = $tmp; $i < $range_end; $i++) {')
|
||||
if val == '_' { return }
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
p.genln('$var_type $val = $i;')
|
||||
}
|
||||
|
||||
@ -404,13 +402,17 @@ fn (p mut Parser) gen_for_map_header(i, tmp, var_typ, val, typ string) {
|
||||
p.genln('string $i = ((string*)keys_$tmp .data)[l];')
|
||||
// TODO don't call map_get() for each key, fetch values while traversing
|
||||
// the tree (replace `map_keys()` above with `map_key_vals()`)
|
||||
if val == '_' { return }
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);')
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) {
|
||||
p.genln('for (int $i = 0; $i < ${varg}->len; $i++) {')
|
||||
if val == '_' { return }
|
||||
if val == '_' {
|
||||
return
|
||||
}
|
||||
p.genln('$var_typ $val = (($var_typ *) $varg->args)[$i];')
|
||||
}
|
||||
|
||||
@ -421,17 +423,17 @@ fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_e
|
||||
}
|
||||
if nr_elems == 0 {
|
||||
p.gen(' TCCSKIP(0) })')
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.gen(' })')
|
||||
}
|
||||
// Need to do this in the second pass, otherwise it goes to the very top of the out.c file
|
||||
if !p.first_pass() {
|
||||
p.cgen.set_placeholder(new_arr_ph,
|
||||
'${new_arr}($nr_elems, $nr_elems, sizeof($typ), EMPTY_ARRAY_OF_ELEMS( $typ, $nr_elems ) { ')
|
||||
p.cgen.set_placeholder(new_arr_ph, '${new_arr}($nr_elems, $nr_elems, sizeof($typ), EMPTY_ARRAY_OF_ELEMS( $typ, $nr_elems ) { ')
|
||||
}
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_pos int, is_cao bool) {
|
||||
fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool, fn_ph, assign_pos int, is_cao bool) {
|
||||
// `a[0] = 7`
|
||||
// curline right now: `a , 0 = 7`
|
||||
mut val := p.cgen.cur_line[assign_pos..]
|
||||
@ -441,7 +443,8 @@ fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_po
|
||||
if is_map {
|
||||
if is_ptr {
|
||||
func = 'map_set('
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
func = 'map_set(&'
|
||||
}
|
||||
// CAO on map is a bit more complicated as it loads
|
||||
@ -463,12 +466,11 @@ fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_po
|
||||
}
|
||||
p.cgen.set_placeholder(fn_ph, func)
|
||||
if is_cao {
|
||||
val = cao_tmp + val.all_before('=') + val.all_after('=')
|
||||
val = cao_tmp + val.all_before('=') + val.all_after('=')
|
||||
}
|
||||
p.gen(', & ($typ []) { $val })')
|
||||
}
|
||||
|
||||
|
||||
// returns true in case of an early return
|
||||
fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
|
||||
// TODO hack. If it's a C type, we may need to add "struct" before declaration:
|
||||
@ -480,7 +482,7 @@ fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
|
||||
}
|
||||
// TODO tm struct struct bug
|
||||
if typ == 'tm' {
|
||||
p.cgen.lines[p.cgen.lines.len-1] = ''
|
||||
p.cgen.lines[p.cgen.lines.len - 1] = ''
|
||||
}
|
||||
p.next()
|
||||
p.check(.lcbr)
|
||||
@ -511,6 +513,7 @@ fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
|
||||
p.check(.rcbr)
|
||||
return true
|
||||
*/
|
||||
|
||||
}
|
||||
p.gen('($t.name*)memdup(&($t.name) {')
|
||||
}
|
||||
@ -527,7 +530,9 @@ fn (p mut Parser) gen_empty_map(typ string) {
|
||||
|
||||
fn (p mut Parser) cast(typ string) {
|
||||
p.gen('(')
|
||||
defer { p.gen(')') }
|
||||
defer {
|
||||
p.gen(')')
|
||||
}
|
||||
p.next()
|
||||
pos := p.cgen.add_placeholder()
|
||||
if p.tok == .rpar {
|
||||
@ -543,8 +548,7 @@ fn (p mut Parser) cast(typ string) {
|
||||
p.warn('casting `$typ` to `$expr_typ` is not needed')
|
||||
}
|
||||
// `face := FT_Face(cobj)` => `FT_Face face = *((FT_Face*)cobj);`
|
||||
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' &&
|
||||
typ != 'byteptr' && !typ.ends_with('*')
|
||||
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' && typ != 'byteptr' && !typ.ends_with('*')
|
||||
p.expected_type = ''
|
||||
// `string(buffer)` => `tos2(buffer)`
|
||||
// `string(buffer, len)` => `tos(buffer, len)`
|
||||
@ -561,7 +565,8 @@ fn (p mut Parser) cast(typ string) {
|
||||
}
|
||||
p.gen(', ')
|
||||
p.check_types(p.expression(), 'int')
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if is_bytearr {
|
||||
p.gen('.data')
|
||||
}
|
||||
@ -617,30 +622,58 @@ fn type_default(typ string) string {
|
||||
return '{0}'
|
||||
}
|
||||
// Default values for other types are not needed because of mandatory initialization
|
||||
match typ {
|
||||
'bool'{ return '0'}
|
||||
'string'{ return 'tos3("")'}
|
||||
'i8'{ return '0'}
|
||||
'i16'{ return '0'}
|
||||
'i64'{ return '0'}
|
||||
'u16'{ return '0'}
|
||||
'u32'{ return '0'}
|
||||
'u64'{ return '0'}
|
||||
'byte'{ return '0'}
|
||||
'int'{ return '0'}
|
||||
'rune'{ return '0'}
|
||||
'f32'{ return '0.0'}
|
||||
'f64'{ return '0.0'}
|
||||
'byteptr'{ return '0'}
|
||||
'voidptr'{ return '0'}
|
||||
else {}
|
||||
}
|
||||
return '{0}'
|
||||
|
||||
|
||||
match typ {
|
||||
'bool' {
|
||||
return '0'
|
||||
}
|
||||
'string' {
|
||||
return 'tos3("")'
|
||||
}
|
||||
'i8' {
|
||||
return '0'
|
||||
}
|
||||
'i16' {
|
||||
return '0'
|
||||
}
|
||||
'i64' {
|
||||
return '0'
|
||||
}
|
||||
'u16' {
|
||||
return '0'
|
||||
}
|
||||
'u32' {
|
||||
return '0'
|
||||
}
|
||||
'u64' {
|
||||
return '0'
|
||||
}
|
||||
'byte' {
|
||||
return '0'
|
||||
}
|
||||
'int' {
|
||||
return '0'
|
||||
}
|
||||
'rune' {
|
||||
return '0'
|
||||
}
|
||||
'f32' {
|
||||
return '0.0'
|
||||
}
|
||||
'f64' {
|
||||
return '0.0'
|
||||
}
|
||||
'byteptr' {
|
||||
return '0'
|
||||
}
|
||||
'voidptr' {
|
||||
return '0'
|
||||
}
|
||||
else {
|
||||
}}
|
||||
return '{0}'
|
||||
// TODO this results in
|
||||
// error: expected a field designator, such as '.field = 4'
|
||||
//- Empty ee= (Empty) { . = {0} } ;
|
||||
// - Empty ee= (Empty) { . = {0} } ;
|
||||
/*
|
||||
return match typ {
|
||||
'bool'{ '0'}
|
||||
@ -661,20 +694,22 @@ else {}
|
||||
else { '{0} '}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
fn (p mut Parser) gen_array_push(ph int, typ, expr_type, tmp, elm_type string) {
|
||||
// Two arrays of the same type?
|
||||
push_array := typ == expr_type
|
||||
if push_array {
|
||||
p.cgen.set_placeholder(ph, '_PUSH_MANY(&' )
|
||||
p.cgen.set_placeholder(ph, '_PUSH_MANY(&')
|
||||
p.gen('), $tmp, $typ)')
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.check_types(expr_type, elm_type)
|
||||
// Pass tmp var info to the _PUSH macro
|
||||
// Prepend tmp initialisation and push call
|
||||
// Don't dereference if it's already a mutable array argument (`fn foo(mut []int)`)
|
||||
push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'}
|
||||
push_call := if typ.contains('*') { '_PUSH(' } else { '_PUSH(&' }
|
||||
p.cgen.set_placeholder(ph, push_call)
|
||||
p.gen('), $tmp, $elm_type)')
|
||||
}
|
||||
|
@ -1,22 +1,21 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
module compiler
|
||||
|
||||
import (
|
||||
strings
|
||||
)
|
||||
|
||||
fn (p mut Parser) get_type2() Type{
|
||||
fn (p mut Parser) get_type2() Type {
|
||||
mut mul := false
|
||||
mut nr_muls := 0
|
||||
mut typ := ''
|
||||
cat := TypeCategory.struct_
|
||||
// multiple returns
|
||||
if p.tok == .lpar {
|
||||
//p.warn('`()` are no longer necessary in multiple returns' +
|
||||
//'\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
||||
// p.warn('`()` are no longer necessary in multiple returns' +
|
||||
// '\nuse `fn foo() int, int {` instead of `fn foo() (int, int) {`')
|
||||
// if p.inside_tuple {p.error('unexpected (')}
|
||||
// p.inside_tuple = true
|
||||
p.check(.lpar)
|
||||
@ -32,7 +31,7 @@ fn (p mut Parser) get_type2() Type{
|
||||
p.check(.rpar)
|
||||
// p.inside_tuple = false
|
||||
typ = p.register_multi_return_stuct(types)
|
||||
return Type {
|
||||
return Type{
|
||||
name: typ
|
||||
mod: p.mod
|
||||
cat: cat
|
||||
@ -40,7 +39,10 @@ fn (p mut Parser) get_type2() Type{
|
||||
}
|
||||
// fn type
|
||||
if p.tok == .key_fn {
|
||||
mut f := Fn{name: '_', mod: p.mod}
|
||||
mut f := Fn{
|
||||
name: '_'
|
||||
mod: p.mod
|
||||
}
|
||||
p.next()
|
||||
line_nr := p.scanner.line_nr
|
||||
p.fn_args(mut f)
|
||||
@ -58,8 +60,9 @@ fn (p mut Parser) get_type2() Type{
|
||||
f.typ = 'void'
|
||||
}
|
||||
// Register anon fn type
|
||||
fn_typ := Type {
|
||||
name: f.typ_str()// 'fn (int, int) string'
|
||||
fn_typ := Type{
|
||||
name: f.typ_str() // 'fn (int, int) string'
|
||||
|
||||
mod: p.mod
|
||||
func: f
|
||||
cat: .func
|
||||
@ -79,8 +82,8 @@ fn (p mut Parser) get_type2() Type{
|
||||
if p.tok == .number || (p.tok == .name && !p.inside_const) {
|
||||
if p.tok == .name {
|
||||
typ += '[${p.mod}__$p.lit]'
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
typ += '[$p.lit]'
|
||||
}
|
||||
p.next()
|
||||
@ -99,10 +102,12 @@ fn (p mut Parser) get_type2() Type{
|
||||
p.error('maps only support string keys for now')
|
||||
}
|
||||
p.check(.rsbr)
|
||||
val_type := p.get_type()// p.check_name()
|
||||
val_type := p.get_type() // p.check_name()
|
||||
typ = 'map_$val_type'
|
||||
p.register_map(typ)
|
||||
return Type{name: typ}
|
||||
return Type{
|
||||
name: typ
|
||||
}
|
||||
}
|
||||
// ptr/ref
|
||||
mut warn := false
|
||||
@ -123,7 +128,8 @@ fn (p mut Parser) get_type2() Type{
|
||||
ti := p.cur_fn.dispatch_of.inst
|
||||
if p.lit in ti.keys() {
|
||||
typ += ti[p.lit]
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
typ += p.lit
|
||||
}
|
||||
// C.Struct import
|
||||
@ -153,8 +159,7 @@ fn (p mut Parser) get_type2() Type{
|
||||
// "typ" not found? try "mod__typ"
|
||||
if t.name == '' && !p.builtin_mod {
|
||||
// && !p.first_pass() {
|
||||
if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') &&
|
||||
!typ.starts_with('[') {
|
||||
if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') && !typ.starts_with('[') {
|
||||
typ = p.prepend_mod(typ)
|
||||
}
|
||||
t = p.table.find_type(typ)
|
||||
@ -164,7 +169,7 @@ fn (p mut Parser) get_type2() Type{
|
||||
// for q in p.table.types {
|
||||
// println(q.name)
|
||||
// }
|
||||
mut t_suggest, tc_suggest := p.table.find_misspelled_type(typ, p, 0.50)
|
||||
mut t_suggest,tc_suggest := p.table.find_misspelled_type(typ, p, 0.50)
|
||||
if t_suggest.len > 0 {
|
||||
t_suggest = '. did you mean: ($tc_suggest) `$t_suggest`'
|
||||
}
|
||||
@ -195,15 +200,14 @@ fn (p mut Parser) get_type2() Type{
|
||||
typ = 'Option_$typ'
|
||||
p.table.register_type_with_parent(typ, 'Option')
|
||||
}
|
||||
|
||||
// Because the code uses * to see if it's a pointer
|
||||
if typ == 'byteptr' {
|
||||
typ = 'byte*'
|
||||
}
|
||||
if typ == 'voidptr' {
|
||||
//if !p.builtin_mod && p.mod != 'os' && p.mod != 'gx' && p.mod != 'gg' && !p.pref.translated {
|
||||
//p.error('voidptr can only be used in unsafe code')
|
||||
//}
|
||||
// if !p.builtin_mod && p.mod != 'os' && p.mod != 'gx' && p.mod != 'gg' && !p.pref.translated {
|
||||
// p.error('voidptr can only be used in unsafe code')
|
||||
// }
|
||||
typ = 'void*'
|
||||
}
|
||||
/*
|
||||
@ -212,6 +216,10 @@ fn (p mut Parser) get_type2() Type{
|
||||
p.error('2 __ in gettype(): typ="$typ"')
|
||||
}
|
||||
*/
|
||||
return Type{name: typ, cat: cat}
|
||||
|
||||
return Type{
|
||||
name: typ
|
||||
cat: cat
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,9 +250,9 @@ fn (p &Parser) gen_fmt() {
|
||||
if s == '' {
|
||||
return
|
||||
}
|
||||
files := ['cgen.v', 'comptime.v', 'cc.v', 'if_match.v']
|
||||
//if !p.file_path.contains('table.v') {return}
|
||||
if !(p.file_name in files) { return }
|
||||
files := ['get_type.v']
|
||||
if !p.file_path.contains('vlib/builtin') {return}
|
||||
//if !(p.file_name in files) { return }
|
||||
path := os.tmpdir() + '/' + p.file_name
|
||||
println('generating ${path}')
|
||||
mut out := os.create(path) or {
|
||||
|
Reference in New Issue
Block a user