From 4b4c47461b074ff099ee2b43fcd509ee5e2ff4c9 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 13 Mar 2020 01:43:30 +0100 Subject: [PATCH] cgen: error fixes; table: simplify; compiler tests --- vlib/v/ast/ast.v | 13 +- vlib/v/checker/checker.v | 6 +- vlib/v/gen/cgen.v | 40 ++- vlib/v/gen/cgen_test.v | 2 + vlib/v/gen/tests/1.c | 4 +- vlib/v/gen/tests/2.c | 2 +- vlib/v/gen/tests/3.c | 2 +- vlib/v/parser/parser.v | 1 + vlib/v/table/atype_symbols.v | 466 -------------------------- vlib/v/table/atypes.v | 621 +++++++++++++++++++++++++++++++++++ vlib/v/table/table.v | 6 +- vlib/v/table/types.v | 153 --------- vlib/v/tests/compiler_test.v | 48 +++ vlib/v/tests/hello.out | 1 + vlib/v/tests/hello.vv | 3 + vlib/v/tests/hello_devs.out | 6 + vlib/v/tests/hello_devs.vv | 7 + vlib/v/tests/os.out | 1 + vlib/v/tests/os.vv | 10 + vlib/v/token/token.v | 40 --- 20 files changed, 757 insertions(+), 675 deletions(-) create mode 100644 vlib/v/table/atypes.v delete mode 100644 vlib/v/table/types.v create mode 100644 vlib/v/tests/compiler_test.v create mode 100644 vlib/v/tests/hello.out create mode 100644 vlib/v/tests/hello.vv create mode 100644 vlib/v/tests/hello_devs.out create mode 100644 vlib/v/tests/hello_devs.vv create mode 100644 vlib/v/tests/os.out create mode 100644 vlib/v/tests/os.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 9794f1bdbb..cef9d8c1de 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -107,6 +107,7 @@ pub: mut_pos int // mut: pub_pos int // pub: pub_mut_pos int // pub mut: + is_c bool } pub struct StructInit { @@ -488,12 +489,12 @@ pub: pub struct AssignExpr { pub: - op token.Kind - pos token.Position - left Expr - val Expr - // mut: - // left_type table.Type + op token.Kind + pos token.Position + left Expr + val Expr +mut: + left_type table.Type } pub struct GotoLabel { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 7b84da073a..7a60821250 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -121,7 +121,6 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type else {} } if c.is_amp { - println('XAXAXAX') return table.type_to_ptr(struct_init.typ) } return struct_init.typ @@ -153,7 +152,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { return left_type } -fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) { +fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) { match assign_expr.left { ast.Ident { if it.kind == .blank_ident { @@ -164,6 +163,7 @@ fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) { } left_type := c.expr(assign_expr.left) c.expected_type = left_type + assign_expr.left_type = left_type // assign_expr.left_type = left_type // t := c.table.get_type_symbol(left_type) // println('setting exp type to $c.expected_type $t.name') @@ -594,7 +594,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type { return it.typ } ast.AssignExpr { - c.assign_expr(it) + c.assign_expr(mut it) } ast.Assoc { scope := c.file.scope.innermost(it.pos.pos) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 163b2e8683..0659fc0096 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -58,6 +58,13 @@ pub fn (g &Gen) typ(t table.Type) string { if nr_muls > 0 { styp += strings.repeat(`*`, nr_muls) } + if styp.starts_with('C__') { + styp = styp[3..] + } + if styp == 'stat' { + // TODO perf and other C structs + styp = 'struct stat' + } return styp } @@ -286,7 +293,9 @@ fn (g mut Gen) stmt(node ast.Stmt) { // g.writeln('\t$field_type_sym.name $field.name;') // } // g.writeln('} $name;') - g.typedefs.writeln('typedef struct $name $name;') + if !it.is_c { + g.typedefs.writeln('typedef struct $name $name;') + } } ast.TypeDecl { g.writeln('// type') @@ -302,6 +311,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { // multi return + // g.write('/*assign*/') if assign_stmt.left.len > assign_stmt.right.len { mut return_type := table.void_type match assign_stmt.right[0] { @@ -399,6 +409,9 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { if name.starts_with('_op_') { name = op_to_fn_name(name) } + if name == 'exit' { + name = 'v_exit' + } // type_name := g.table.type_to_str(it.return_type) type_name := g.typ(it.return_type) g.write('$type_name ${name}(') @@ -503,17 +516,30 @@ fn (g mut Gen) expr(node ast.Expr) { } ast.AssignExpr { g.is_assign_expr = true + mut str_add := false + if it.left_type == table.string_type_idx && it.op == .plus_assign { + // str += str2 => `str = string_add(str, str2)` + g.expr(it.left) + g.write(' = string_add(') + str_add = true + } g.expr(it.left) // arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val` - if !g.is_array_set { + if !g.is_array_set && !str_add { g.write(' $it.op.str() ') } + else if str_add { + g.write(', ') + } g.is_assign_expr = false g.expr(it.val) if g.is_array_set { g.write(' })') g.is_array_set = false } + else if str_add { + g.write(')') + } } ast.Assoc { g.write('/* assoc */') @@ -523,6 +549,9 @@ fn (g mut Gen) expr(node ast.Expr) { } ast.CallExpr { mut name := it.name.replace('.', '__') + if name == 'exit' { + name = 'v_exit' + } if it.is_c { // Skip "C__" g.is_c_call = true @@ -834,6 +863,9 @@ fn (g mut Gen) expr(node ast.Expr) { g.expr(it.exprs[i]) g.writeln(', ') } + if it.fields.len == 0 { + g.write('0') + } g.write('}') if g.is_amp { g.write(', sizeof($styp))') @@ -865,6 +897,7 @@ fn (g mut Gen) expr(node ast.Expr) { } fn (g mut Gen) infix_expr(node ast.InfixExpr) { + // g.write('/*infix*/') // if it.left_type == table.string_type_idx { // g.write('/*$node.left_type str*/') // } @@ -1103,6 +1136,9 @@ fn (g mut Gen) write_sorted_types() { fn (g mut Gen) write_types(types []table.TypeSymbol) { for typ in types { + if typ.name.starts_with('C.') { + continue + } // sym := g.table.get_type_symbol(typ) match typ.info { table.Struct { diff --git a/vlib/v/gen/cgen_test.v b/vlib/v/gen/cgen_test.v index 09fb6295b8..7ca8ad4bb0 100644 --- a/vlib/v/gen/cgen_test.v +++ b/vlib/v/gen/cgen_test.v @@ -49,6 +49,8 @@ fn compare_texts(a, b, path string) bool { println('${path}: got\n$a') println('${term_fail} ${i}') println(term.red('i=$i "$line_a" expected="$line_b"')) + // println(lines_b[i + 1]) + // println(lines_b[i + 2]) // exit(1) return false } diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index d54e919ae3..fd0f2cea83 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -59,7 +59,7 @@ int main() { println(int_str(localmod__pub_int_const)); int g = ((int)(3.0)); byte* bytes = ((byte*)(0)); - User* user_ptr = (User*)memdup(&(User){}, sizeof(User)); + User* user_ptr = (User*)memdup(&(User){0}, sizeof(User)); return 0; } @@ -82,7 +82,7 @@ i < 10; i++) { }); array_User users = new_array_from_c_array(1, 1, sizeof(array_User), (User[]){ (User){ - }, + 0}, }); bool b = (*(bool*)array_get(bools, 0)); array_string mystrings = new_array_from_c_array(2, 2, sizeof(array_string), (string[]){ diff --git a/vlib/v/gen/tests/2.c b/vlib/v/gen/tests/2.c index 82fda87f93..cd62b27898 100644 --- a/vlib/v/gen/tests/2.c +++ b/vlib/v/gen/tests/2.c @@ -30,7 +30,7 @@ void init_user() { User get_user() { User user = (User){ - }; + 0}; return user; } diff --git a/vlib/v/gen/tests/3.c b/vlib/v/gen/tests/3.c index 5ffaa7d703..d2f8c67825 100644 --- a/vlib/v/gen/tests/3.c +++ b/vlib/v/gen/tests/3.c @@ -17,7 +17,7 @@ tos3(""), int main() { User user = (User){ -}; +0}; user.age = 10; user.age++; user.name = tos3("bob"); diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 1fab2dc3d9..e8c2971acc 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1440,6 +1440,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { mut_pos: mut_pos pub_pos: pub_pos pub_mut_pos: pub_mut_pos + is_c: is_c } } diff --git a/vlib/v/table/atype_symbols.v b/vlib/v/table/atype_symbols.v index 35f3c5d82a..657ffda581 100644 --- a/vlib/v/table/atype_symbols.v +++ b/vlib/v/table/atype_symbols.v @@ -3,469 +3,3 @@ // that can be found in the LICENSE file. module table -import ( - strings -) - -pub type TypeInfo = Array | ArrayFixed | Map | Struct | -MultiReturn | Alias | Enum | SumType | Fn - -pub struct TypeSymbol { -pub: - parent_idx int -mut: - info TypeInfo - kind Kind - name string - methods []Fn - // is_sum bool -} - -pub const ( -// primitive types - void_type_idx = 1 - voidptr_type_idx = 2 - byteptr_type_idx = 3 - charptr_type_idx = 4 - i8_type_idx = 5 - i16_type_idx = 6 - int_type_idx = 7 - i64_type_idx = 8 - byte_type_idx = 9 - u16_type_idx = 10 - u32_type_idx = 11 - u64_type_idx = 12 - f32_type_idx = 13 - f64_type_idx = 14 - char_type_idx = 15 - bool_type_idx = 16 - none_type_idx = 17 - // advanced / defined from v structs - string_type_idx = 18 - array_type_idx = 19 - map_type_idx = 20 -) - -pub const ( - builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', - 'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'struct', - 'mapnode', 'ustring'] -) - -pub struct MultiReturn { -pub: - name string -mut: - types []Type -} - -pub enum Kind { - placeholder - void - voidptr - byteptr - charptr - i8 - i16 - int - i64 - byte - u16 - u32 - u64 - f32 - f64 - char - bool - none_ - string - array - array_fixed - map - struct_ - multi_return - sum_type - alias - enum_ - function -} - -pub fn (t &TypeSymbol) str() string { - return t.name.replace('array_', '[]') -} - -[inline] -pub fn (t &TypeSymbol) enum_info() Enum { - match t.info { - Enum { - return it - } - else { - panic('TypeSymbol.enum_info(): no enum info for type: $t.name') - } - } -} - -[inline] -pub fn (t &TypeSymbol) mr_info() MultiReturn { - match t.info { - MultiReturn { - return it - } - else { - panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') - } - } -} - -[inline] -pub fn (t &TypeSymbol) array_info() Array { - match t.info { - Array { - return it - } - else { - panic('TypeSymbol.array_info(): no array info for type: $t.name') - } - } -} - -[inline] -pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { - match t.info { - ArrayFixed { - return it - } - else { - panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') - } - } -} - -[inline] -pub fn (t &TypeSymbol) map_info() Map { - match t.info { - Map { - return it - } - else { - panic('TypeSymbol.map_info(): no map info for type: $t.name') - } - } -} - -/* -pub fn (t TypeSymbol) str() string { - return t.name -} -*/ - - -pub fn (t mut Table) register_builtin_type_symbols() { - // reserve index 0 so nothing can go there - // save index check, 0 will mean not found - t.register_type_symbol(TypeSymbol{ - kind: .placeholder - name: 'reserved_0' - }) - t.register_type_symbol(TypeSymbol{ - kind: .void - name: 'void' - }) - t.register_type_symbol(TypeSymbol{ - kind: .voidptr - name: 'voidptr' - }) - t.register_type_symbol(TypeSymbol{ - kind: .byteptr - name: 'byteptr' - }) - t.register_type_symbol(TypeSymbol{ - kind: .charptr - name: 'charptr' - }) - t.register_type_symbol(TypeSymbol{ - kind: .i8 - name: 'i8' - }) - t.register_type_symbol(TypeSymbol{ - kind: .i16 - name: 'i16' - }) - t.register_type_symbol(TypeSymbol{ - kind: .int - name: 'int' - }) - t.register_type_symbol(TypeSymbol{ - kind: .i64 - name: 'i64' - }) - t.register_type_symbol(TypeSymbol{ - kind: .byte - name: 'byte' - }) - t.register_type_symbol(TypeSymbol{ - kind: .u16 - name: 'u16' - }) - t.register_type_symbol(TypeSymbol{ - kind: .u32 - name: 'u32' - }) - t.register_type_symbol(TypeSymbol{ - kind: .u64 - name: 'u64' - }) - t.register_type_symbol(TypeSymbol{ - kind: .f32 - name: 'f32' - }) - t.register_type_symbol(TypeSymbol{ - kind: .f64 - name: 'f64' - }) - t.register_type_symbol(TypeSymbol{ - kind: .char - name: 'char' - }) - t.register_type_symbol(TypeSymbol{ - kind: .bool - name: 'bool' - }) - t.register_type_symbol(TypeSymbol{ - kind: .none_ - name: 'none' - }) - t.register_type_symbol(TypeSymbol{ - kind: .string - name: 'string' - }) - t.register_type_symbol(TypeSymbol{ - kind: .array - name: 'array' - }) - t.register_type_symbol(TypeSymbol{ - kind: .map - name: 'map' - }) - // TODO: remove. for v1 map compatibility - map_string_string_idx := t.find_or_register_map(string_type, string_type) - map_string_int_idx := t.find_or_register_map(string_type, int_type) - t.register_type_symbol(TypeSymbol{ - kind: .alias - name: 'map_string' - parent_idx: map_string_string_idx - }) - t.register_type_symbol(TypeSymbol{ - kind: .alias - name: 'map_int' - parent_idx: map_string_int_idx - }) -} - -[inline] -pub fn (t &TypeSymbol) is_int() bool { - return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] -} - -[inline] -pub fn (t &TypeSymbol) is_float() bool { - return t.kind in [.f32, .f64] -} - -[inline] -pub fn (t &TypeSymbol) is_number() bool { - return t.is_int() || t.is_float() -} - -pub fn (k Kind) str() string { - k_str := match k { - .placeholder{ - 'placeholder' - } - .void{ - 'void' - } - .voidptr{ - 'voidptr' - } - .charptr{ - 'charptr' - } - .byteptr{ - 'byteptr' - } - .struct_{ - 'struct' - } - .int{ - 'int' - } - .i8{ - 'i8' - } - .i16{ - 'i16' - } - .i64{ - 'i64' - } - .byte{ - 'byte' - } - .u16{ - 'u16' - } - .u32{ - 'u32' - } - .u64{ - 'u64' - } - .f32{ - 'f32' - } - .f64{ - 'f64' - } - .string{ - 'string' - } - .char{ - 'char' - } - .bool{ - 'bool' - } - .none_{ - 'none' - } - .array{ - 'array' - } - .array_fixed{ - 'array_fixed' - } - .map{ - 'map' - } - .multi_return{ - 'multi_return' - } - .sum_type{ - 'sum_type' - } - .alias{ - 'alias' - } - .enum_{ - 'enum' - } - else { - 'unknown'} - } - return k_str -} - -pub fn (kinds []Kind) str() string { - mut kinds_str := '' - for i, k in kinds { - kinds_str += k.str() - if i < kinds.len - 1 { - kinds_str += '_' - } - } - return kinds_str -} - -pub struct Struct { -pub mut: - fields []Field -} - -pub struct Enum { -pub mut: - vals []string -} - -pub struct Alias { -pub: - foo string -} - -pub struct Field { -pub: - name string -mut: - typ Type -} - -pub struct Array { -pub: - nr_dims int -mut: - elem_type Type -} - -pub struct ArrayFixed { -pub: - nr_dims int - size int -mut: - elem_type Type -} - -pub struct Map { -pub mut: - key_type Type - value_type Type -} - -pub struct SumType { -pub: - variants []Type -} - -pub fn (table &Table) type_to_str(t Type) string { - sym := table.get_type_symbol(t) - if sym.kind == .multi_return { - mut res := '(' - mr_info := sym.info as MultiReturn - for i, typ in mr_info.types { - res += table.type_to_str(typ) - if i < mr_info.types.len - 1 { - res += ', ' - } - } - res += ')' - return res - } - mut res := sym.name - if sym.kind == .array { - res = res.replace('array_', '[]') - } - else if sym.kind == .map { - res = res.replace('map_string_', 'map[string]') - } - // mod.submod.submod2.Type => submod2.Type - if res.contains('.') { - vals := res.split('.') - if vals.len > 2 { - res = vals[vals.len - 2] + '.' + vals[vals.len - 1] - } - } - if type_is_optional(t) { - res = '?' + res - } - nr_muls := type_nr_muls(t) - if nr_muls > 0 { - res = strings.repeat(`&`, nr_muls) + res - } - /* - if res.starts_with(cur_mod +'.') { - res = res[cur_mod.len+1.. ] - } - */ - - return res -} diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v new file mode 100644 index 0000000000..a52f526b1f --- /dev/null +++ b/vlib/v/table/atypes.v @@ -0,0 +1,621 @@ +module table + +import ( + strings +) + +pub type Type int + +pub type TypeInfo = Array | ArrayFixed | Map | Struct | +MultiReturn | Alias | Enum | SumType | Fn + +pub struct TypeSymbol { +pub: + parent_idx int +mut: + info TypeInfo + kind Kind + name string + methods []Fn + // is_sum bool +} + +pub enum TypeExtra { + unset + optional + variadic +} + +pub fn (types []Type) contains(typ Type) bool { + for t in types { + if int(typ) == int(t) { + return true + } + } + return false +} + +// return underlying TypeSymbol idx +[inline] +pub fn type_idx(t Type) int { + return u16(t) & 0xffff +} + +// return nr_muls +[inline] +pub fn type_nr_muls(t Type) int { + return (int(t)>>16) & 0xff +} + +// return true if pointer (nr_muls>0) +[inline] +pub fn type_is_ptr(t Type) bool { + return type_nr_muls(t) > 0 // || t == voidptr_type_idx +} +// set nr_muls on Type and return it +[inline] +pub fn type_set_nr_muls(t Type, nr_muls int) Type { + if nr_muls < 0 || nr_muls > 255 { + panic('typ_set_nr_muls: nr_muls must be between 0 & 255') + } + return (int(type_extra(t))<<24) | (nr_muls<<16) | u16(type_idx(t)) +} + +// increments nr_nuls on Type and return it +[inline] +pub fn type_to_ptr(t Type) Type { + nr_muls := type_nr_muls(t) + if nr_muls == 255 { + panic('type_to_pre: nr_muls is already at max of 255') + } + return (int(type_extra(t))<<24) | ((nr_muls + 1)<<16) | u16(type_idx(t)) +} + +// decrement nr_muls on Type and return it +[inline] +pub fn type_deref(t Type) Type { + nr_muls := type_nr_muls(t) + if nr_muls == 0 { + panic('deref: type `$t` is not a pointer') + } + return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) +} + +// return extra info +[inline] +pub fn type_extra(t Type) TypeExtra { + return (int(t)>>24) & 0xff +} + +// set extra info +[inline] +pub fn type_set_extra(t Type, extra TypeExtra) Type { + return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t)) +} + +[inline] +pub fn type_is_optional(t Type) bool { + return type_extra(t) == .optional +} + +[inline] +pub fn type_to_optional(t Type) Type { + return type_set_extra(t, .optional) +} + +[inline] +pub fn type_is_variadic(t Type) bool { + return type_extra(t) == .variadic +} + +[inline] +pub fn type_to_variadic(t Type) Type { + return type_set_extra(t, .variadic) +} + +// new type with idx of TypeSymbol, not pointer (nr_muls=0) +[inline] +pub fn new_type(idx int) Type { + if idx < 1 || idx > 65536 { + panic('new_type_id: idx must be between 1 & 65536') + } + return idx +} + +// return Type idx of TypeSymbol & specify if ptr (nr_muls) +[inline] +pub fn new_type_ptr(idx int, nr_muls int) Type { + if idx < 1 || idx > 65536 { + panic('typ_ptr: idx must be between 1 & 65536') + } + if nr_muls < 0 || nr_muls > 255 { + panic('typ_ptr: nr_muls must be between 0 & 255') + } + return (nr_muls<<16) | u16(idx) +} + +/* +pub fn is_number(typ Type) bool { + typ_sym := c.table.get_type_symbol(typ) + return typ_sym.is_int() + //idx := type_idx(typ) + //return idx in [int_type_idx, byte_type_idx, u64_type_idx] +} +*/ + + +pub const ( +// primitive types + void_type_idx = 1 + voidptr_type_idx = 2 + byteptr_type_idx = 3 + charptr_type_idx = 4 + i8_type_idx = 5 + i16_type_idx = 6 + int_type_idx = 7 + i64_type_idx = 8 + byte_type_idx = 9 + u16_type_idx = 10 + u32_type_idx = 11 + u64_type_idx = 12 + f32_type_idx = 13 + f64_type_idx = 14 + char_type_idx = 15 + bool_type_idx = 16 + none_type_idx = 17 + // advanced / defined from v structs + string_type_idx = 18 + array_type_idx = 19 + map_type_idx = 20 +) + +pub const ( + number_idxs = [int_type_idx, byte_type_idx, u16_type_idx, i16_type_idx, i64_type_idx, u32_type_idx, u64_type_idx] +) + +pub const ( + void_type = new_type(void_type_idx) + voidptr_type = new_type(voidptr_type_idx) + byteptr_type = new_type(byteptr_type_idx) + charptr_type = new_type(charptr_type_idx) + i8_type = new_type(i8_type_idx) + int_type = new_type(int_type_idx) + i16_type = new_type(i16_type_idx) + i64_type = new_type(i64_type_idx) + byte_type = new_type(byte_type_idx) + u16_type = new_type(u16_type_idx) + u32_type = new_type(u32_type_idx) + u64_type = new_type(u64_type_idx) + f32_type = new_type(f32_type_idx) + f64_type = new_type(f64_type_idx) + char_type = new_type(char_type_idx) + bool_type = new_type(bool_type_idx) + none_type = new_type(none_type_idx) + string_type = new_type(string_type_idx) + array_type = new_type(array_type_idx) + map_type = new_type(map_type_idx) +) + +pub const ( + builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', + 'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'struct', + 'mapnode', 'ustring'] +) + +pub struct MultiReturn { +pub: + name string +mut: + types []Type +} + +pub enum Kind { + placeholder + void + voidptr + byteptr + charptr + i8 + i16 + int + i64 + byte + u16 + u32 + u64 + f32 + f64 + char + bool + none_ + string + array + array_fixed + map + struct_ + multi_return + sum_type + alias + enum_ + function +} + +pub fn (t &TypeSymbol) str() string { + return t.name.replace('array_', '[]') +} + +[inline] +pub fn (t &TypeSymbol) enum_info() Enum { + match t.info { + Enum { + return it + } + else { + panic('TypeSymbol.enum_info(): no enum info for type: $t.name') + } + } +} + +[inline] +pub fn (t &TypeSymbol) mr_info() MultiReturn { + match t.info { + MultiReturn { + return it + } + else { + panic('TypeSymbol.mr_info(): no multi return info for type: $t.name') + } + } +} + +[inline] +pub fn (t &TypeSymbol) array_info() Array { + match t.info { + Array { + return it + } + else { + panic('TypeSymbol.array_info(): no array info for type: $t.name') + } + } +} + +[inline] +pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed { + match t.info { + ArrayFixed { + return it + } + else { + panic('TypeSymbol.array_fixed(): no array fixed info for type: $t.name') + } + } +} + +[inline] +pub fn (t &TypeSymbol) map_info() Map { + match t.info { + Map { + return it + } + else { + panic('TypeSymbol.map_info(): no map info for type: $t.name') + } + } +} + +/* +pub fn (t TypeSymbol) str() string { + return t.name +} +*/ + + +pub fn (t mut Table) register_builtin_type_symbols() { + // reserve index 0 so nothing can go there + // save index check, 0 will mean not found + t.register_type_symbol(TypeSymbol{ + kind: .placeholder + name: 'reserved_0' + }) + t.register_type_symbol(TypeSymbol{ + kind: .void + name: 'void' + }) + t.register_type_symbol(TypeSymbol{ + kind: .voidptr + name: 'voidptr' + }) + t.register_type_symbol(TypeSymbol{ + kind: .byteptr + name: 'byteptr' + }) + t.register_type_symbol(TypeSymbol{ + kind: .charptr + name: 'charptr' + }) + t.register_type_symbol(TypeSymbol{ + kind: .i8 + name: 'i8' + }) + t.register_type_symbol(TypeSymbol{ + kind: .i16 + name: 'i16' + }) + t.register_type_symbol(TypeSymbol{ + kind: .int + name: 'int' + }) + t.register_type_symbol(TypeSymbol{ + kind: .i64 + name: 'i64' + }) + t.register_type_symbol(TypeSymbol{ + kind: .byte + name: 'byte' + }) + t.register_type_symbol(TypeSymbol{ + kind: .u16 + name: 'u16' + }) + t.register_type_symbol(TypeSymbol{ + kind: .u32 + name: 'u32' + }) + t.register_type_symbol(TypeSymbol{ + kind: .u64 + name: 'u64' + }) + t.register_type_symbol(TypeSymbol{ + kind: .f32 + name: 'f32' + }) + t.register_type_symbol(TypeSymbol{ + kind: .f64 + name: 'f64' + }) + t.register_type_symbol(TypeSymbol{ + kind: .char + name: 'char' + }) + t.register_type_symbol(TypeSymbol{ + kind: .bool + name: 'bool' + }) + t.register_type_symbol(TypeSymbol{ + kind: .none_ + name: 'none' + }) + t.register_type_symbol(TypeSymbol{ + kind: .string + name: 'string' + }) + t.register_type_symbol(TypeSymbol{ + kind: .array + name: 'array' + }) + t.register_type_symbol(TypeSymbol{ + kind: .map + name: 'map' + }) + // TODO: remove. for v1 map compatibility + map_string_string_idx := t.find_or_register_map(string_type, string_type) + map_string_int_idx := t.find_or_register_map(string_type, int_type) + t.register_type_symbol(TypeSymbol{ + kind: .alias + name: 'map_string' + parent_idx: map_string_string_idx + }) + t.register_type_symbol(TypeSymbol{ + kind: .alias + name: 'map_int' + parent_idx: map_string_int_idx + }) +} + +[inline] +pub fn (t &TypeSymbol) is_int() bool { + return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] +} + +[inline] +pub fn (t &TypeSymbol) is_float() bool { + return t.kind in [.f32, .f64] +} + +[inline] +pub fn (t &TypeSymbol) is_number() bool { + return t.is_int() || t.is_float() +} + +pub fn (k Kind) str() string { + k_str := match k { + .placeholder{ + 'placeholder' + } + .void{ + 'void' + } + .voidptr{ + 'voidptr' + } + .charptr{ + 'charptr' + } + .byteptr{ + 'byteptr' + } + .struct_{ + 'struct' + } + .int{ + 'int' + } + .i8{ + 'i8' + } + .i16{ + 'i16' + } + .i64{ + 'i64' + } + .byte{ + 'byte' + } + .u16{ + 'u16' + } + .u32{ + 'u32' + } + .u64{ + 'u64' + } + .f32{ + 'f32' + } + .f64{ + 'f64' + } + .string{ + 'string' + } + .char{ + 'char' + } + .bool{ + 'bool' + } + .none_{ + 'none' + } + .array{ + 'array' + } + .array_fixed{ + 'array_fixed' + } + .map{ + 'map' + } + .multi_return{ + 'multi_return' + } + .sum_type{ + 'sum_type' + } + .alias{ + 'alias' + } + .enum_{ + 'enum' + } + else { + 'unknown'} + } + return k_str +} + +pub fn (kinds []Kind) str() string { + mut kinds_str := '' + for i, k in kinds { + kinds_str += k.str() + if i < kinds.len - 1 { + kinds_str += '_' + } + } + return kinds_str +} + +pub struct Struct { +pub mut: + fields []Field +} + +pub struct Enum { +pub mut: + vals []string +} + +pub struct Alias { +pub: + foo string +} + +pub struct Field { +pub: + name string +mut: + typ Type +} + +pub struct Array { +pub: + nr_dims int +mut: + elem_type Type +} + +pub struct ArrayFixed { +pub: + nr_dims int + size int +mut: + elem_type Type +} + +pub struct Map { +pub mut: + key_type Type + value_type Type +} + +pub struct SumType { +pub: + variants []Type +} + +pub fn (table &Table) type_to_str(t Type) string { + sym := table.get_type_symbol(t) + if sym.kind == .multi_return { + mut res := '(' + mr_info := sym.info as MultiReturn + for i, typ in mr_info.types { + res += table.type_to_str(typ) + if i < mr_info.types.len - 1 { + res += ', ' + } + } + res += ')' + return res + } + mut res := sym.name + if sym.kind == .array { + res = res.replace('array_', '[]') + } + else if sym.kind == .map { + res = res.replace('map_string_', 'map[string]') + } + // mod.submod.submod2.Type => submod2.Type + if res.contains('.') { + vals := res.split('.') + if vals.len > 2 { + res = vals[vals.len - 2] + '.' + vals[vals.len - 1] + } + } + if type_is_optional(t) { + res = '?' + res + } + nr_muls := type_nr_muls(t) + if nr_muls > 0 { + res = strings.repeat(`&`, nr_muls) + res + } + /* + if res.starts_with(cur_mod +'.') { + res = res[cur_mod.len+1.. ] + } + */ + + return res +} diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 23fc788749..a1d34fe760 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -3,6 +3,10 @@ // that can be found in the LICENSE file. module table +import ( + strings +) + pub struct Table { // struct_fields map[string][]string pub mut: @@ -56,7 +60,7 @@ pub fn (t mut Table) register_global(name string, typ Type) { // mod: p.mod // is_mut: true // idx: -1 - + } } diff --git a/vlib/v/table/types.v b/vlib/v/table/types.v deleted file mode 100644 index f4950a931c..0000000000 --- a/vlib/v/table/types.v +++ /dev/null @@ -1,153 +0,0 @@ -module table - -pub type Type int - -pub enum TypeExtra { - unset - optional - variadic -} - -pub fn (types []Type) contains(typ Type) bool { - for t in types { - if int(typ) == int(t) { - return true - } - } - return false -} - -// return underlying TypeSymbol idx -[inline] -pub fn type_idx(t Type) int { - return u16(t) & 0xffff -} - -// return nr_muls -[inline] -pub fn type_nr_muls(t Type) int { - return (int(t)>>16) & 0xff -} - -// return true if pointer (nr_muls>0) -[inline] -pub fn type_is_ptr(t Type) bool { - return type_nr_muls(t) > 0 // || t == voidptr_type_idx -} -// set nr_muls on Type and return it -[inline] -pub fn type_set_nr_muls(t Type, nr_muls int) Type { - if nr_muls < 0 || nr_muls > 255 { - panic('typ_set_nr_muls: nr_muls must be between 0 & 255') - } - return (int(type_extra(t))<<24) | (nr_muls<<16) | u16(type_idx(t)) -} - -// increments nr_nuls on Type and return it -[inline] -pub fn type_to_ptr(t Type) Type { - nr_muls := type_nr_muls(t) - if nr_muls == 255 { - panic('type_to_pre: nr_muls is already at max of 255') - } - return (int(type_extra(t))<<24) | ((nr_muls + 1)<<16) | u16(type_idx(t)) -} - -// decrement nr_muls on Type and return it -[inline] -pub fn type_deref(t Type) Type { - nr_muls := type_nr_muls(t) - if nr_muls == 0 { - panic('deref: type `$t` is not a pointer') - } - return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) -} - -// return extra info -[inline] -pub fn type_extra(t Type) TypeExtra { - return (int(t)>>24) & 0xff -} - -// set extra info -[inline] -pub fn type_set_extra(t Type, extra TypeExtra) Type { - return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t)) -} - -[inline] -pub fn type_is_optional(t Type) bool { - return type_extra(t) == .optional -} - -[inline] -pub fn type_to_optional(t Type) Type { - return type_set_extra(t, .optional) -} - -[inline] -pub fn type_is_variadic(t Type) bool { - return type_extra(t) == .variadic -} - -[inline] -pub fn type_to_variadic(t Type) Type { - return type_set_extra(t, .variadic) -} - -// new type with idx of TypeSymbol, not pointer (nr_muls=0) -[inline] -pub fn new_type(idx int) Type { - if idx < 1 || idx > 65536 { - panic('new_type_id: idx must be between 1 & 65536') - } - return idx -} - -// return Type idx of TypeSymbol & specify if ptr (nr_muls) -[inline] -pub fn new_type_ptr(idx int, nr_muls int) Type { - if idx < 1 || idx > 65536 { - panic('typ_ptr: idx must be between 1 & 65536') - } - if nr_muls < 0 || nr_muls > 255 { - panic('typ_ptr: nr_muls must be between 0 & 255') - } - return (nr_muls<<16) | u16(idx) -} - -pub const ( - number_idxs = [int_type_idx, byte_type_idx, u16_type_idx, i16_type_idx, i64_type_idx, u32_type_idx, u64_type_idx] -) -/* -pub fn is_number(typ Type) bool { - typ_sym := c.table.get_type_symbol(typ) - return typ_sym.is_int() - //idx := type_idx(typ) - //return idx in [int_type_idx, byte_type_idx, u64_type_idx] -} -*/ - - -pub const ( - void_type = new_type(void_type_idx) - voidptr_type = new_type(voidptr_type_idx) - byteptr_type = new_type(byteptr_type_idx) - charptr_type = new_type(charptr_type_idx) - i8_type = new_type(i8_type_idx) - int_type = new_type(int_type_idx) - i16_type = new_type(i16_type_idx) - i64_type = new_type(i64_type_idx) - byte_type = new_type(byte_type_idx) - u16_type = new_type(u16_type_idx) - u32_type = new_type(u32_type_idx) - u64_type = new_type(u64_type_idx) - f32_type = new_type(f32_type_idx) - f64_type = new_type(f64_type_idx) - char_type = new_type(char_type_idx) - bool_type = new_type(bool_type_idx) - none_type = new_type(none_type_idx) - string_type = new_type(string_type_idx) - array_type = new_type(array_type_idx) - map_type = new_type(map_type_idx) -) diff --git a/vlib/v/tests/compiler_test.v b/vlib/v/tests/compiler_test.v new file mode 100644 index 0000000000..d8545b7437 --- /dev/null +++ b/vlib/v/tests/compiler_test.v @@ -0,0 +1,48 @@ +import os +import term + +fn test_all() { + files := os.ls('.') or { + panic(err) + } + for file in files { + if !file.ends_with('.vv') { + continue + } + print(file + ' ') + program := file.replace('.vv', '.v') + os.cp(file, program) or { + panic(err) + } + os.rm('exe') + x := os.exec('v -o exe -cflags "-w" -cg -backend experimental $program') or { + panic(err) + } + println(x.output.limit(30)) + os.rm(program) + res := os.exec('./exe') or { + println('nope') + panic(err) + } + // println('============') + // println(res.output) + // println('============') + mut expected := os.read_file(program.replace('.v', '') + '.out') or { + panic(err) + } + expected = expected.trim_space() + found := res.output.trim_space() + if expected != found { + println(term.red('FAIL')) + println('============') + println('expected:') + println(expected) + println('\nfound:') + println(found) + println('============') + } + else { + println(term.green('OK')) + } + } +} diff --git a/vlib/v/tests/hello.out b/vlib/v/tests/hello.out new file mode 100644 index 0000000000..3b18e512db --- /dev/null +++ b/vlib/v/tests/hello.out @@ -0,0 +1 @@ +hello world diff --git a/vlib/v/tests/hello.vv b/vlib/v/tests/hello.vv new file mode 100644 index 0000000000..24c0d2aa24 --- /dev/null +++ b/vlib/v/tests/hello.vv @@ -0,0 +1,3 @@ +fn main() { + println('hello world') +} diff --git a/vlib/v/tests/hello_devs.out b/vlib/v/tests/hello_devs.out new file mode 100644 index 0000000000..adf8207172 --- /dev/null +++ b/vlib/v/tests/hello_devs.out @@ -0,0 +1,6 @@ +Hello, game developers! +Hello, web developers! +Hello, tools developers! +Hello, science developers! +Hello, systems developers! +Hello, embedded developers! diff --git a/vlib/v/tests/hello_devs.vv b/vlib/v/tests/hello_devs.vv new file mode 100644 index 0000000000..5ae559e979 --- /dev/null +++ b/vlib/v/tests/hello_devs.vv @@ -0,0 +1,7 @@ +fn main() { + areas := ['game', 'web', 'tools', 'science', 'systems', 'embedded'] + for i :=0;i` | `>=` - .lt, .le, .gt, .ge, .ne, .eq, - // `,` - .comma] -} - -// is_right_assoc returns true if the token is right associative -pub fn (tok Token) is_right_assoc() bool { - return tok.kind in [ - // `+` | `-` | `!` - .plus, .minus, .not, // unary - // `=` | `+=` | `-=` | `*=` | `/=` - .assign, .plus_assign, .minus_assign, .mult_assign, .div_assign, - // `%=` | `>>=` | `<<=` - .mod_assign, .right_shift_assign, .left_shift_assign, - // `&=` | `^=` | `|=` - .and_assign, .xor_assign, .or_assign] -} -*/ - - pub fn (tok Kind) is_relational() bool { return tok in [ // `<` | `<=` | `>` | `>=`