cgen: error fixes; table: simplify; compiler tests
parent
b43ac2783d
commit
4b4c47461b
|
@ -107,6 +107,7 @@ pub:
|
||||||
mut_pos int // mut:
|
mut_pos int // mut:
|
||||||
pub_pos int // pub:
|
pub_pos int // pub:
|
||||||
pub_mut_pos int // pub mut:
|
pub_mut_pos int // pub mut:
|
||||||
|
is_c bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
|
@ -488,12 +489,12 @@ pub:
|
||||||
|
|
||||||
pub struct AssignExpr {
|
pub struct AssignExpr {
|
||||||
pub:
|
pub:
|
||||||
op token.Kind
|
op token.Kind
|
||||||
pos token.Position
|
pos token.Position
|
||||||
left Expr
|
left Expr
|
||||||
val Expr
|
val Expr
|
||||||
// mut:
|
mut:
|
||||||
// left_type table.Type
|
left_type table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GotoLabel {
|
pub struct GotoLabel {
|
||||||
|
|
|
@ -121,7 +121,6 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
if c.is_amp {
|
if c.is_amp {
|
||||||
println('XAXAXAX')
|
|
||||||
return table.type_to_ptr(struct_init.typ)
|
return table.type_to_ptr(struct_init.typ)
|
||||||
}
|
}
|
||||||
return 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
|
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 {
|
match assign_expr.left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .blank_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)
|
left_type := c.expr(assign_expr.left)
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
|
assign_expr.left_type = left_type
|
||||||
// assign_expr.left_type = left_type
|
// assign_expr.left_type = left_type
|
||||||
// t := c.table.get_type_symbol(left_type)
|
// t := c.table.get_type_symbol(left_type)
|
||||||
// println('setting exp type to $c.expected_type $t.name')
|
// 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
|
return it.typ
|
||||||
}
|
}
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
c.assign_expr(it)
|
c.assign_expr(mut it)
|
||||||
}
|
}
|
||||||
ast.Assoc {
|
ast.Assoc {
|
||||||
scope := c.file.scope.innermost(it.pos.pos)
|
scope := c.file.scope.innermost(it.pos.pos)
|
||||||
|
|
|
@ -58,6 +58,13 @@ pub fn (g &Gen) typ(t table.Type) string {
|
||||||
if nr_muls > 0 {
|
if nr_muls > 0 {
|
||||||
styp += strings.repeat(`*`, nr_muls)
|
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
|
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('\t$field_type_sym.name $field.name;')
|
||||||
// }
|
// }
|
||||||
// g.writeln('} $name;')
|
// g.writeln('} $name;')
|
||||||
g.typedefs.writeln('typedef struct $name $name;')
|
if !it.is_c {
|
||||||
|
g.typedefs.writeln('typedef struct $name $name;')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
ast.TypeDecl {
|
||||||
g.writeln('// type')
|
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) {
|
fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
// multi return
|
// multi return
|
||||||
|
// g.write('/*assign*/')
|
||||||
if assign_stmt.left.len > assign_stmt.right.len {
|
if assign_stmt.left.len > assign_stmt.right.len {
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
match assign_stmt.right[0] {
|
match assign_stmt.right[0] {
|
||||||
|
@ -399,6 +409,9 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if name.starts_with('_op_') {
|
if name.starts_with('_op_') {
|
||||||
name = op_to_fn_name(name)
|
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.table.type_to_str(it.return_type)
|
||||||
type_name := g.typ(it.return_type)
|
type_name := g.typ(it.return_type)
|
||||||
g.write('$type_name ${name}(')
|
g.write('$type_name ${name}(')
|
||||||
|
@ -503,17 +516,30 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
g.is_assign_expr = true
|
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)
|
g.expr(it.left)
|
||||||
// arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val`
|
// 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() ')
|
g.write(' $it.op.str() ')
|
||||||
}
|
}
|
||||||
|
else if str_add {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
g.is_assign_expr = false
|
g.is_assign_expr = false
|
||||||
g.expr(it.val)
|
g.expr(it.val)
|
||||||
if g.is_array_set {
|
if g.is_array_set {
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
g.is_array_set = false
|
g.is_array_set = false
|
||||||
}
|
}
|
||||||
|
else if str_add {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.Assoc {
|
ast.Assoc {
|
||||||
g.write('/* assoc */')
|
g.write('/* assoc */')
|
||||||
|
@ -523,6 +549,9 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
mut name := it.name.replace('.', '__')
|
mut name := it.name.replace('.', '__')
|
||||||
|
if name == 'exit' {
|
||||||
|
name = 'v_exit'
|
||||||
|
}
|
||||||
if it.is_c {
|
if it.is_c {
|
||||||
// Skip "C__"
|
// Skip "C__"
|
||||||
g.is_c_call = true
|
g.is_c_call = true
|
||||||
|
@ -834,6 +863,9 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
g.writeln(', ')
|
g.writeln(', ')
|
||||||
}
|
}
|
||||||
|
if it.fields.len == 0 {
|
||||||
|
g.write('0')
|
||||||
|
}
|
||||||
g.write('}')
|
g.write('}')
|
||||||
if g.is_amp {
|
if g.is_amp {
|
||||||
g.write(', sizeof($styp))')
|
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) {
|
fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
||||||
|
// g.write('/*infix*/')
|
||||||
// if it.left_type == table.string_type_idx {
|
// if it.left_type == table.string_type_idx {
|
||||||
// g.write('/*$node.left_type str*/')
|
// 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) {
|
fn (g mut Gen) write_types(types []table.TypeSymbol) {
|
||||||
for typ in types {
|
for typ in types {
|
||||||
|
if typ.name.starts_with('C.') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// sym := g.table.get_type_symbol(typ)
|
// sym := g.table.get_type_symbol(typ)
|
||||||
match typ.info {
|
match typ.info {
|
||||||
table.Struct {
|
table.Struct {
|
||||||
|
|
|
@ -49,6 +49,8 @@ fn compare_texts(a, b, path string) bool {
|
||||||
println('${path}: got\n$a')
|
println('${path}: got\n$a')
|
||||||
println('${term_fail} ${i}')
|
println('${term_fail} ${i}')
|
||||||
println(term.red('i=$i "$line_a" expected="$line_b"'))
|
println(term.red('i=$i "$line_a" expected="$line_b"'))
|
||||||
|
// println(lines_b[i + 1])
|
||||||
|
// println(lines_b[i + 2])
|
||||||
// exit(1)
|
// exit(1)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ int main() {
|
||||||
println(int_str(localmod__pub_int_const));
|
println(int_str(localmod__pub_int_const));
|
||||||
int g = ((int)(3.0));
|
int g = ((int)(3.0));
|
||||||
byte* bytes = ((byte*)(0));
|
byte* bytes = ((byte*)(0));
|
||||||
User* user_ptr = (User*)memdup(&(User){}, sizeof(User));
|
User* user_ptr = (User*)memdup(&(User){0}, sizeof(User));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ i < 10; i++) {
|
||||||
});
|
});
|
||||||
array_User users = new_array_from_c_array(1, 1, sizeof(array_User), (User[]){
|
array_User users = new_array_from_c_array(1, 1, sizeof(array_User), (User[]){
|
||||||
(User){
|
(User){
|
||||||
},
|
0},
|
||||||
});
|
});
|
||||||
bool b = (*(bool*)array_get(bools, 0));
|
bool b = (*(bool*)array_get(bools, 0));
|
||||||
array_string mystrings = new_array_from_c_array(2, 2, sizeof(array_string), (string[]){
|
array_string mystrings = new_array_from_c_array(2, 2, sizeof(array_string), (string[]){
|
||||||
|
|
|
@ -30,7 +30,7 @@ void init_user() {
|
||||||
|
|
||||||
User get_user() {
|
User get_user() {
|
||||||
User user = (User){
|
User user = (User){
|
||||||
};
|
0};
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ tos3(""),
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
User user = (User){
|
User user = (User){
|
||||||
};
|
0};
|
||||||
user.age = 10;
|
user.age = 10;
|
||||||
user.age++;
|
user.age++;
|
||||||
user.name = tos3("bob");
|
user.name = tos3("bob");
|
||||||
|
|
|
@ -1440,6 +1440,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
mut_pos: mut_pos
|
mut_pos: mut_pos
|
||||||
pub_pos: pub_pos
|
pub_pos: pub_pos
|
||||||
pub_mut_pos: pub_mut_pos
|
pub_mut_pos: pub_mut_pos
|
||||||
|
is_c: is_c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,469 +3,3 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module table
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -3,6 +3,10 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module table
|
module table
|
||||||
|
|
||||||
|
import (
|
||||||
|
strings
|
||||||
|
)
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
// struct_fields map[string][]string
|
// struct_fields map[string][]string
|
||||||
pub mut:
|
pub mut:
|
||||||
|
|
|
@ -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)
|
|
||||||
)
|
|
|
@ -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'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
hello world
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println('hello world')
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
Hello, game developers!
|
||||||
|
Hello, web developers!
|
||||||
|
Hello, tools developers!
|
||||||
|
Hello, science developers!
|
||||||
|
Hello, systems developers!
|
||||||
|
Hello, embedded developers!
|
|
@ -0,0 +1,7 @@
|
||||||
|
fn main() {
|
||||||
|
areas := ['game', 'web', 'tools', 'science', 'systems', 'embedded']
|
||||||
|
for i :=0;i<areas.len; i++{
|
||||||
|
area:=areas[i]
|
||||||
|
println('Hello, $area developers!')
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
compiler_test.v
|
|
@ -0,0 +1,10 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
files := os.ls('.') or { panic(err) }
|
||||||
|
for file in files {
|
||||||
|
if file.ends_with('_test.v') {
|
||||||
|
println(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -427,46 +427,6 @@ pub fn (tok Token) is_unary() bool {
|
||||||
.plus, .minus, .not, .bit_not, .mul, .amp]
|
.plus, .minus, .not, .bit_not, .mul, .amp]
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc),
|
|
||||||
// or only ones with the same precedence?
|
|
||||||
// is_left_assoc returns true if the token is left associative
|
|
||||||
pub fn (tok Token) is_left_assoc() bool {
|
|
||||||
return tok.kind in [
|
|
||||||
// `.`
|
|
||||||
.dot,
|
|
||||||
// `+` | `-`
|
|
||||||
.plus, .minus, // additive
|
|
||||||
// .number,
|
|
||||||
// `++` | `--`
|
|
||||||
.inc, .dec,
|
|
||||||
// `*` | `/` | `%`
|
|
||||||
.mul, .div, .mod,
|
|
||||||
// `^` | `||` | `&`
|
|
||||||
.xor, .logical_or, .and,
|
|
||||||
// `==` | `!=`
|
|
||||||
.eq, .ne,
|
|
||||||
// `<` | `<=` | `>` | `>=`
|
|
||||||
.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 {
|
pub fn (tok Kind) is_relational() bool {
|
||||||
return tok in [
|
return tok in [
|
||||||
// `<` | `<=` | `>` | `>=`
|
// `<` | `<=` | `>` | `>=`
|
||||||
|
|
Loading…
Reference in New Issue