table: bring back parse_cflag()

pull/4321/head
Alexander Medvednikov 2020-04-09 15:59:19 +02:00
parent c0d86eb651
commit 2b685fc80a
4 changed files with 147 additions and 122 deletions

View File

@ -24,17 +24,17 @@ fn (v &Builder) get_os_cflags() []CFlag {
if v.pref.compile_defines.len > 0 { if v.pref.compile_defines.len > 0 {
ctimedefines << v.pref.compile_defines ctimedefines << v.pref.compile_defines
} }
// QTODO
/*
for flag in v.table.cflags { for flag in v.table.cflags {
if flag.os == '' || (flag.os == 'linux' && v.pref.os == .linux) || (flag.os == 'darwin' && v.pref.os == .mac) || (flag.os == 'freebsd' && v.pref.os == .freebsd) || (flag.os == 'windows' && v.pref.os == .windows) || (flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler != 'msvc') || (flag.os == 'solaris' && v.pref.os == .solaris) { if flag.os == '' || (flag.os == 'linux' && v.pref.os == .linux) || (flag.os == 'darwin' &&
v.pref.os == .mac) || (flag.os == 'freebsd' && v.pref.os == .freebsd) || (flag.os == 'windows' &&
v.pref.os == .windows) || (flag.os == 'mingw' && v.pref.os == .windows && v.pref.ccompiler !=
'msvc') || (flag.os == 'solaris' && v.pref.os == .solaris) {
flags << flag flags << flag
} }
if flag.os in ctimedefines { if flag.os in ctimedefines {
flags << flag flags << flag
} }
} }
*/
return flags return flags
} }
@ -65,93 +65,6 @@ fn (cf &CFlag) format() string {
return '$cf.name $value'.trim_space() return '$cf.name $value'.trim_space()
} }
// check if cflag is in table
/*
QTODO
fn (table &Table) has_cflag(cflag CFlag) bool {
for cf in table.cflags {
if cf.os == cflag.os && cf.name == cflag.name && cf.value == cflag.value {
return true
}
}
return false
}
// parse the flags to (table.cflags) []CFlag
// Note: clean up big time (joe-c)
fn (table mut Table) parse_cflag(cflag string, mod string, ctimedefines []string) ?bool {
allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L', ]
flag_orig := cflag.trim_space()
mut flag := flag_orig
if flag == '' {
return true
}
mut fos := ''
mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris']
allowed_os_overrides << ctimedefines
for os_override in allowed_os_overrides {
if !flag.starts_with( os_override ) { continue }
pos := flag.index(' ') or {
return none
}
fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space()
}
for {
mut name := ''
mut value := ''
if flag[0] == `-` {
for f in allowed_flags {
i := 1 + f.len
if i <= flag.len && f == flag[1..i] {
name = flag[..i].trim_space()
flag = flag[i..].trim_space()
break
}
}
}
mut index := flag.index(' -') or {
-1
}
for index > -1 {
mut has_next := false
for f in allowed_flags {
i := index + 2 + f.len
if i <= flag.len && f == flag[index + 2..i] {
value = flag[..index + 1].trim_space()
flag = flag[index + 1..].trim_space()
has_next = true
break
}
}
if has_next {
break
}
index = flag.index_after(' -', index + 1)
}
if index == -1 {
value = flag.trim_space()
}
if (name in ['-I', '-l', '-L']) && value == '' {
hint := if name == '-l' { 'library name' } else { 'path' }
return error('bad #flag `$flag_orig`: missing $hint after `$name`')
}
cf := CFlag{
mod: mod
os: fos
name: name
value: value
}
if !table.has_cflag(cf) {
table.cflags << cf
}
if index == -1 {
break
}
}
return true
}
*/
// TODO: implement msvc specific c_options_before_target and c_options_after_target ... // TODO: implement msvc specific c_options_before_target and c_options_after_target ...
fn (cflags []CFlag) c_options_before_target_msvc() string { fn (cflags []CFlag) c_options_before_target_msvc() string {
return '' return ''

View File

@ -451,7 +451,7 @@ fn (f mut Fmt) expr(node ast.Expr) {
f.writeln('\t$it.var_name |') f.writeln('\t$it.var_name |')
// TODO StructInit copy pasta // TODO StructInit copy pasta
for i, field in it.fields { for i, field in it.fields {
f.write('$field: ') f.write('\t$field: ')
f.expr(it.exprs[i]) f.expr(it.exprs[i])
f.writeln('') f.writeln('')
} }

View File

@ -0,0 +1,93 @@
// Copyright (c) 2019-2020 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 table
import v.builder
// check if cflag is in table
fn (table &Table) has_cflag(cflag builder.CFlag) bool {
for cf in table.cflags {
if cf.os == cflag.os && cf.name == cflag.name && cf.value == cflag.value {
return true
}
}
return false
}
// parse the flags to (table.cflags) []CFlag
// Note: clean up big time (joe-c)
fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool {
allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L']
flag_orig := cflag.trim_space()
mut flag := flag_orig
if flag == '' {
return true
}
mut fos := ''
mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris']
allowed_os_overrides << ctimedefines
for os_override in allowed_os_overrides {
if !flag.starts_with(os_override) {
continue
}
pos := flag.index(' ') or {
return none
}
fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space()
}
for {
mut name := ''
mut value := ''
if flag[0] == `-` {
for f in allowed_flags {
i := 1 + f.len
if i <= flag.len && f == flag[1..i] {
name = flag[..i].trim_space()
flag = flag[i..].trim_space()
break
}
}
}
mut index := flag.index(' -') or {
-1
}
for index > -1 {
mut has_next := false
for f in allowed_flags {
i := index + 2 + f.len
if i <= flag.len && f == flag[index + 2..i] {
value = flag[..index + 1].trim_space()
flag = flag[index + 1..].trim_space()
has_next = true
break
}
}
if has_next {
break
}
index = flag.index_after(' -', index + 1)
}
if index == -1 {
value = flag.trim_space()
}
if (name in ['-I', '-l', '-L']) && value == '' {
hint := if name == '-l' { 'library name' } else { 'path' }
return error('bad #flag `$flag_orig`: missing $hint after `$name`')
}
cf := builder.CFlag{
mod: mod
os: fos
name: name
value: value
}
if !table.has_cflag(cf) {
table.cflags << cf
}
if index == -1 {
break
}
}
return true
}

View File

@ -3,18 +3,19 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module table
import os import (
os
v.builder
)
pub struct Table { pub struct Table {
// struct_fields map[string][]string
pub mut: pub mut:
types []TypeSymbol types []TypeSymbol
// type_idxs Hashmap
type_idxs map[string]int type_idxs map[string]int
// fns Hashmap
fns map[string]Fn fns map[string]Fn
imports []string // List of all imports imports []string // List of all imports
modules []string // List of all modules registered by the application modules []string // List of all modules registered by the application
cflags []builder.CFlag // TODO a different module? importing builder from table feels weird
} }
pub struct Fn { pub struct Fn {
@ -35,10 +36,10 @@ pub:
pub struct Var { pub struct Var {
pub: pub:
name string name string
is_mut bool is_mut bool
mut: mut:
typ Type typ Type
} }
pub fn new_table() &Table { pub fn new_table() &Table {
@ -133,7 +134,7 @@ pub fn (t &Table) type_has_method(s &TypeSymbol, name string) bool {
pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn { pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
// println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') // println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
mut ts := s mut ts := s
for { for {
if method := ts.find_method(name) { if method := ts.find_method(name) {
return method return method
} }
@ -157,7 +158,7 @@ pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool {
pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field { pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field {
// println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') // println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
mut ts := s mut ts := s
for { for {
if field := ts.find_field(name) { if field := ts.find_field(name) {
return field return field
} }
@ -206,10 +207,9 @@ pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int {
existing_type := t.types[existing_idx] existing_type := t.types[existing_idx]
t.types[existing_idx] = { t.types[existing_idx] = {
typ | typ |
kind:existing_type.kind kind: existing_type.kind
} }
} } else {
else {
t.types[existing_idx] = typ t.types[existing_idx] = typ
} }
} }
@ -230,7 +230,7 @@ pub fn (t mut Table) register_type_symbol(typ TypeSymbol) int {
// println('overriding type placeholder `$typ.name`') // println('overriding type placeholder `$typ.name`')
t.types[existing_idx] = { t.types[existing_idx] = {
typ | typ |
methods:ex_type.methods methods: ex_type.methods
} }
return existing_idx return existing_idx
} }
@ -241,7 +241,7 @@ pub fn (t mut Table) register_type_symbol(typ TypeSymbol) int {
// panic('cannot register type `$typ.name`, another type with this name exists') // panic('cannot register type `$typ.name`, another type with this name exists')
return -1 return -1
} }
} }
} }
typ_idx := t.types.len typ_idx := t.types.len
t.types << typ t.types << typ
@ -259,17 +259,33 @@ pub fn (t &Table) known_type(name string) bool {
[inline] [inline]
pub fn (t &Table) array_name(elem_type Type, nr_dims int) string { pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
elem_type_sym := t.get_type_symbol(elem_type) elem_type_sym := t.get_type_symbol(elem_type)
return 'array_${elem_type_sym.name}' + if type_is_ptr(elem_type) { '_ptr' } else { '' } + if nr_dims > 1 { '_${nr_dims}d' } else { '' } return 'array_${elem_type_sym.name}' + if type_is_ptr(elem_type) {
'_ptr'
} else {
''
} + if nr_dims > 1 {
'_${nr_dims}d'
} else {
''
}
} }
[inline] [inline]
pub fn (t &Table) array_fixed_name(elem_type Type, size int, nr_dims int) string { pub fn (t &Table) array_fixed_name(elem_type Type, size, nr_dims int) string {
elem_type_sym := t.get_type_symbol(elem_type) elem_type_sym := t.get_type_symbol(elem_type)
return 'array_fixed_${elem_type_sym.name}_${size}' + if type_is_ptr(elem_type) { '_ptr' } else { '' } + if nr_dims > 1 { '_${nr_dims}d' } else { '' } return 'array_fixed_${elem_type_sym.name}_${size}' + if type_is_ptr(elem_type) {
'_ptr'
} else {
''
} + if nr_dims > 1 {
'_${nr_dims}d'
} else {
''
}
} }
[inline] [inline]
pub fn (t &Table) map_name(key_type Type, value_type Type) string { pub fn (t &Table) map_name(key_type, value_type Type) string {
key_type_sym := t.get_type_symbol(key_type) key_type_sym := t.get_type_symbol(key_type)
value_type_sym := t.get_type_symbol(value_type) value_type_sym := t.get_type_symbol(value_type)
suffix := if type_is_ptr(value_type) { '_ptr' } else { '' } suffix := if type_is_ptr(value_type) { '_ptr' } else { '' }
@ -317,7 +333,7 @@ pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int {
return t.register_type_symbol(array_type) return t.register_type_symbol(array_type)
} }
pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size int, nr_dims int) int { pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size, nr_dims int) int {
name := t.array_fixed_name(elem_type, size, nr_dims) name := t.array_fixed_name(elem_type, size, nr_dims)
// existing // existing
existing_idx := t.type_idxs[name] existing_idx := t.type_idxs[name]
@ -402,7 +418,7 @@ pub fn (t &Table) value_type(typ Type) Type {
info := typ_sym.info as Map info := typ_sym.info as Map
return info.value_type return info.value_type
} }
if typ_sym.kind == .string && table.type_is_ptr(typ) { if typ_sym.kind == .string && type_is_ptr(typ) {
// (&string)[i] => string // (&string)[i] => string
return string_type return string_type
} }
@ -439,24 +455,25 @@ pub fn (t &Table) check(got, expected Type) bool {
if exp_idx == voidptr_type_idx || got_idx == voidptr_type_idx { if exp_idx == voidptr_type_idx || got_idx == voidptr_type_idx {
return true return true
} }
if (exp_idx in pointer_type_idxs || exp_idx in number_type_idxs) // if (exp_idx in pointer_type_idxs || exp_idx in number_type_idxs) && (got_idx in pointer_type_idxs ||
&& (got_idx in pointer_type_idxs || got_idx in number_type_idxs) { got_idx in number_type_idxs) {
return true return true
} }
// see hack in checker IndexExpr line #691 // see hack in checker IndexExpr line #691
if (got_idx == byte_type_idx && exp_idx == byteptr_type_idx) // if (got_idx == byte_type_idx && exp_idx == byteptr_type_idx) || (exp_idx == byte_type_idx &&
|| (exp_idx == byte_type_idx && got_idx == byteptr_type_idx) { got_idx == byteptr_type_idx) {
return true return true
} }
if (got_idx == char_type_idx && exp_idx == charptr_type_idx) // if (got_idx == char_type_idx && exp_idx == charptr_type_idx) || (exp_idx == char_type_idx &&
|| (exp_idx == char_type_idx && got_idx == charptr_type_idx) { got_idx == charptr_type_idx) {
return true return true
} }
// # NOTE: use symbols from this point on for perf // # NOTE: use symbols from this point on for perf
got_type_sym := t.get_type_symbol(got) got_type_sym := t.get_type_symbol(got)
exp_type_sym := t.get_type_symbol(expected) exp_type_sym := t.get_type_symbol(expected)
// allow enum value to be used as int // allow enum value to be used as int
if (got_type_sym.is_int() && exp_type_sym.kind == .enum_) || (exp_type_sym.is_int() && got_type_sym.kind == .enum_) { if (got_type_sym.is_int() && exp_type_sym.kind == .enum_) || (exp_type_sym.is_int() &&
got_type_sym.kind == .enum_) {
return true return true
} }
// TODO // TODO
@ -475,11 +492,13 @@ pub fn (t &Table) check(got, expected Type) bool {
} }
// TODO // TODO
// accept [] when an expected type is an array // accept [] when an expected type is an array
if got_type_sym.kind == .array && got_type_sym.name == 'array_void' && exp_type_sym.kind == .array { if got_type_sym.kind == .array && got_type_sym.name == 'array_void' && exp_type_sym.kind ==
.array {
return true return true
} }
// type alias // type alias
if (got_type_sym.kind == .alias && got_type_sym.parent_idx == exp_idx) || (exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx) { if (got_type_sym.kind == .alias && got_type_sym.parent_idx == exp_idx) || (exp_type_sym.kind ==
.alias && exp_type_sym.parent_idx == got_idx) {
return true return true
} }
// sum type // sum type
@ -512,7 +531,7 @@ pub fn (t &Table) check(got, expected Type) bool {
// Once we have a module format we can read from module file instead // Once we have a module format we can read from module file instead
// this is not optimal // this is not optimal
pub fn (table &Table) qualify_module(mod string, file_path string) string { pub fn (table &Table) qualify_module(mod, file_path string) string {
for m in table.imports { for m in table.imports {
if m.contains('.') && m.contains(mod) { if m.contains('.') && m.contains(mod) {
m_parts := m.split('.') m_parts := m.split('.')