cgen: lots of fixes
parent
1143320b8b
commit
de55a26cfe
|
@ -255,7 +255,7 @@ fn (a array) slice2(start, _end int, end_max bool) array {
|
||||||
}
|
}
|
||||||
|
|
||||||
// array.clone returns an independent copy of a given array
|
// array.clone returns an independent copy of a given array
|
||||||
pub fn (a array) clone() array {
|
pub fn (a &array) clone() array {
|
||||||
mut size := a.cap * a.element_size
|
mut size := a.cap * a.element_size
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
size++
|
size++
|
||||||
|
@ -270,7 +270,7 @@ pub fn (a array) clone() array {
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (a array) slice_clone(start, _end int) array {
|
fn (a &array) slice_clone(start, _end int) array {
|
||||||
mut end := _end
|
mut end := _end
|
||||||
$if !no_bounds_checking? {
|
$if !no_bounds_checking? {
|
||||||
if start > end {
|
if start > end {
|
||||||
|
@ -316,8 +316,6 @@ pub fn (a3 mut array) push_many(val voidptr, size int) {
|
||||||
// handle `arr << arr`
|
// handle `arr << arr`
|
||||||
copy := a3.clone()
|
copy := a3.clone()
|
||||||
a3.ensure_cap(a3.len + size)
|
a3.ensure_cap(a3.len + size)
|
||||||
C.printf("%d", a3.len*2)
|
|
||||||
println(a3.len*2)
|
|
||||||
//C.memcpy(a.data, copy.data, copy.element_size * copy.len)
|
//C.memcpy(a.data, copy.data, copy.element_size * copy.len)
|
||||||
C.memcpy(a3.data + a3.element_size * a3.len, copy.data, a3.element_size * size)
|
C.memcpy(a3.data + a3.element_size * a3.len, copy.data, a3.element_size * size)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -190,7 +190,7 @@ pub fn (c rune) str() string {
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
str.str[i] = int(c)>>8 * (3 - i) & 0xff
|
str.str[i] = int(c)>>8 * (3 - i) & 0xff
|
||||||
}
|
}
|
||||||
str[len] = `\0`
|
str.str[len] = `\0`
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,11 @@ pub fn (b mut Builder) write(s string) {
|
||||||
b.len += s.len
|
b.len += s.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (b mut Builder) go_back(n int) {
|
||||||
|
b.buf.trim(b.buf.len-n)
|
||||||
|
//b.len -= n
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (b mut Builder) writeln(s string) {
|
pub fn (b mut Builder) writeln(s string) {
|
||||||
// for c in s {
|
// for c in s {
|
||||||
// b.buf << c
|
// b.buf << c
|
||||||
|
|
|
@ -161,6 +161,7 @@ mut:
|
||||||
// func Expr
|
// func Expr
|
||||||
name string
|
name string
|
||||||
args []Expr
|
args []Expr
|
||||||
|
arg_types []table.Type
|
||||||
is_c bool
|
is_c bool
|
||||||
muts []bool
|
muts []bool
|
||||||
or_block OrExpr
|
or_block OrExpr
|
||||||
|
@ -171,12 +172,14 @@ pub struct MethodCallExpr {
|
||||||
pub:
|
pub:
|
||||||
// tok token.Token
|
// tok token.Token
|
||||||
pos token.Position
|
pos token.Position
|
||||||
expr Expr
|
expr Expr // `user` in `user.register()`
|
||||||
name string
|
name string
|
||||||
args []Expr
|
args []Expr
|
||||||
muts []bool
|
muts []bool
|
||||||
or_block OrExpr
|
or_block OrExpr
|
||||||
mut:
|
mut:
|
||||||
|
expr_type table.Type // type of `user`
|
||||||
|
receiver_type table.Type // User
|
||||||
typ table.Type
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ mut:
|
||||||
errors []string
|
errors []string
|
||||||
expected_type table.Type
|
expected_type table.Type
|
||||||
fn_return_type table.Type // current function's return type
|
fn_return_type table.Type // current function's return type
|
||||||
|
// is_amp bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &table.Table) Checker {
|
pub fn new_checker(table &table.Table) Checker {
|
||||||
|
@ -250,7 +251,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||||
// TODO: clean this up, remove dupe code & consider merging method/fn call everywhere
|
// TODO: clean this up, remove dupe code & consider merging method/fn call everywhere
|
||||||
pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) table.Type {
|
pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) table.Type {
|
||||||
typ := c.expr(method_call_expr.expr)
|
typ := c.expr(method_call_expr.expr)
|
||||||
method_call_expr.typ = typ
|
method_call_expr.expr_type = typ
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
name := method_call_expr.name
|
name := method_call_expr.name
|
||||||
if typ_sym.kind == .array && name in ['filter', 'clone'] {
|
if typ_sym.kind == .array && name in ['filter', 'clone'] {
|
||||||
|
@ -281,6 +282,10 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr)
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
if method := typ_sym.find_method(name) {
|
if method := typ_sym.find_method(name) {
|
||||||
|
if name == 'clone' {
|
||||||
|
println('CLONE nr args=$method.args.len')
|
||||||
|
}
|
||||||
|
method_call_expr.receiver_type = method.args[0].typ
|
||||||
for i, arg_expr in method_call_expr.args {
|
for i, arg_expr in method_call_expr.args {
|
||||||
c.expected_type = method.args[i].typ
|
c.expected_type = method.args[i].typ
|
||||||
c.expr(arg_expr)
|
c.expr(arg_expr)
|
||||||
|
|
|
@ -19,6 +19,7 @@ mut:
|
||||||
is_c_call bool // e.g. `C.printf("v")`
|
is_c_call bool // e.g. `C.printf("v")`
|
||||||
is_assign_expr bool
|
is_assign_expr bool
|
||||||
is_array_set bool
|
is_array_set bool
|
||||||
|
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||||
|
@ -42,6 +43,7 @@ pub fn (g mut Gen) init() {
|
||||||
g.definitions.writeln('#include <inttypes.h>') // int64_t etc
|
g.definitions.writeln('#include <inttypes.h>') // int64_t etc
|
||||||
g.definitions.writeln(c_builtin_types)
|
g.definitions.writeln(c_builtin_types)
|
||||||
g.definitions.writeln(c_headers)
|
g.definitions.writeln(c_headers)
|
||||||
|
g.write_builtin_types()
|
||||||
g.write_array_types()
|
g.write_array_types()
|
||||||
g.write_sorted_types()
|
g.write_sorted_types()
|
||||||
g.write_multi_return_types()
|
g.write_multi_return_types()
|
||||||
|
@ -211,7 +213,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
g.write('while (')
|
g.write('while (')
|
||||||
|
if it.is_inf {
|
||||||
|
g.write('1')
|
||||||
|
}
|
||||||
|
else {
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
|
}
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
|
@ -289,19 +296,19 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
panic('expected call')
|
panic('expected call')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mr_typ_sym := g.table.get_type_symbol(return_type)
|
|
||||||
mr_var_name := 'mr_$assign_stmt.pos.pos'
|
mr_var_name := 'mr_$assign_stmt.pos.pos'
|
||||||
g.write('$mr_typ_sym.name $mr_var_name = ')
|
mr_typ_str := g.typ(return_type)
|
||||||
|
g.write('$mr_typ_str $mr_var_name = ')
|
||||||
g.expr(assign_stmt.right[0])
|
g.expr(assign_stmt.right[0])
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
for i, ident in assign_stmt.left {
|
for i, ident in assign_stmt.left {
|
||||||
ident_var_info := ident.var_info()
|
ident_var_info := ident.var_info()
|
||||||
var_type_sym := g.table.get_type_symbol(ident_var_info.typ)
|
styp := g.typ(ident_var_info.typ)
|
||||||
if ident.kind == .blank_ident {
|
if ident.kind == .blank_ident {
|
||||||
g.writeln('{$var_type_sym.name _ = $mr_var_name->arg[$i]};')
|
g.writeln('{ $styp _ = ${mr_var_name}.arg$i};')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.writeln('$var_type_sym.name $ident.name = $mr_var_name->arg[$i];')
|
g.writeln('$styp $ident.name = ${mr_var_name}.arg$i;')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,24 +317,29 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
for i, ident in assign_stmt.left {
|
for i, ident in assign_stmt.left {
|
||||||
val := assign_stmt.right[i]
|
val := assign_stmt.right[i]
|
||||||
ident_var_info := ident.var_info()
|
ident_var_info := ident.var_info()
|
||||||
var_type_sym := g.table.get_type_symbol(ident_var_info.typ)
|
styp := g.typ(ident_var_info.typ)
|
||||||
if ident.kind == .blank_ident {
|
if ident.kind == .blank_ident {
|
||||||
is_call := match val {
|
is_call := match val {
|
||||||
ast.CallExpr { true }
|
ast.CallExpr{
|
||||||
ast.MethodCallExpr { true }
|
true
|
||||||
else { false }
|
}
|
||||||
|
ast.MethodCallExpr{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
false}
|
||||||
}
|
}
|
||||||
if is_call {
|
if is_call {
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('{$var_type_sym.name _ = ')
|
g.write('{$styp _ = ')
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('$var_type_sym.name $ident.name = ')
|
g.write('$styp $ident.name = ')
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
}
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
|
@ -359,13 +371,14 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.definitions.write('$type_name ${name}(')
|
g.definitions.write('$type_name ${name}(')
|
||||||
}
|
}
|
||||||
// Receiver is the first argument
|
// Receiver is the first argument
|
||||||
|
/*
|
||||||
if it.is_method {
|
if it.is_method {
|
||||||
mut styp := g.typ(it.receiver.typ)
|
mut styp := g.typ(it.receiver.typ)
|
||||||
// if table.type_nr_muls(it.receiver.typ) > 0 {
|
// if table.type_nr_muls(it.receiver.typ) > 0 {
|
||||||
// if it.rec_mut {
|
// if it.rec_mut {
|
||||||
// styp += '*'
|
// styp += '*'
|
||||||
// }
|
// }
|
||||||
g.write('$styp $it.receiver.name')
|
g.write('$styp $it.receiver.name ')
|
||||||
// TODO mut
|
// TODO mut
|
||||||
g.definitions.write('$styp $it.receiver.name')
|
g.definitions.write('$styp $it.receiver.name')
|
||||||
if it.args.len > 0 {
|
if it.args.len > 0 {
|
||||||
|
@ -373,6 +386,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.definitions.write(', ')
|
g.definitions.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//
|
//
|
||||||
no_names := it.args.len > 0 && it.args[0].name == 'arg_1'
|
no_names := it.args.len > 0 && it.args[0].name == 'arg_1'
|
||||||
for i, arg in it.args {
|
for i, arg in it.args {
|
||||||
|
@ -459,13 +473,24 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
name = name[3..]
|
name = name[3..]
|
||||||
}
|
}
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
g.call_args(it.args)
|
g.call_args(it.args, it.muts)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
g.is_c_call = false
|
g.is_c_call = false
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
|
// g.write('/*cast*/')
|
||||||
|
if g.is_amp {
|
||||||
|
// &Foo(0) => ((Foo*)0)
|
||||||
|
g.out.go_back(1)
|
||||||
|
}
|
||||||
if it.typ == table.string_type_idx {
|
if it.typ == table.string_type_idx {
|
||||||
|
// tos(str, len), tos2(str)
|
||||||
|
if it.has_arg {
|
||||||
g.write('tos(')
|
g.write('tos(')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.write('tos2(')
|
||||||
|
}
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
if it.has_arg {
|
if it.has_arg {
|
||||||
g.write(',')
|
g.write(',')
|
||||||
|
@ -474,10 +499,16 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
styp := g.table.type_to_str(it.typ)
|
// styp := g.table.type_to_str(it.typ)
|
||||||
g.write('($styp)(')
|
styp := g.typ(it.typ)
|
||||||
|
// g.write('($styp)(')
|
||||||
|
g.write('(($styp)(')
|
||||||
|
// if g.is_amp {
|
||||||
|
// g.write('*')
|
||||||
|
// }
|
||||||
|
// g.write(')(')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.write(')')
|
g.write('))')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CharLiteral {
|
ast.CharLiteral {
|
||||||
|
@ -491,8 +522,13 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
name := it.name.replace('.', '__')
|
name := it.name.replace('.', '__')
|
||||||
|
if name.starts_with('C__') {
|
||||||
|
g.write(name[3..])
|
||||||
|
}
|
||||||
|
else {
|
||||||
g.write(name)
|
g.write(name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
// If expression? Assign the value to a temp var.
|
// If expression? Assign the value to a temp var.
|
||||||
// Previously ?: was used, but it's too unreliable.
|
// Previously ?: was used, but it's too unreliable.
|
||||||
|
@ -544,9 +580,11 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write('/* guard */')
|
g.write('/* guard */')
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
|
//
|
||||||
g.index_expr(it)
|
g.index_expr(it)
|
||||||
}
|
}
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
|
// sdf
|
||||||
g.infix_expr(it)
|
g.infix_expr(it)
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
|
@ -614,20 +652,30 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
ast.MethodCallExpr {
|
ast.MethodCallExpr {
|
||||||
mut receiver_name := 'TODO'
|
mut receiver_name := 'TODO'
|
||||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
if it.typ != 0 {
|
if it.expr_type != 0 {
|
||||||
typ_sym := g.table.get_type_symbol(it.typ)
|
typ_sym := g.table.get_type_symbol(it.expr_type)
|
||||||
receiver_name = typ_sym.name
|
receiver_name = typ_sym.name
|
||||||
// if typ_sym.kind == .array {
|
if typ_sym.kind == .array && receiver_name.starts_with('array_') {
|
||||||
// receiver_name = 'array'
|
// array_byte_clone => array_clone
|
||||||
// }
|
receiver_name = 'array'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
name := '${receiver_name}_$it.name'.replace('.', '__')
|
name := '${receiver_name}_$it.name'.replace('.', '__')
|
||||||
|
// if it.receiver_type != 0 {
|
||||||
|
// g.write('/*${g.typ(it.receiver_type)}*/')
|
||||||
|
// g.write('/*expr_type=${g.typ(it.expr_type)} rec type=${g.typ(it.receiver_type)}*/')
|
||||||
|
// }
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
|
if table.type_is_ptr(it.receiver_type) && !table.type_is_ptr(it.expr_type) {
|
||||||
|
// The receiver is a reference, but the caller provided a value
|
||||||
|
// Add `&` automatically.
|
||||||
|
g.write('&')
|
||||||
|
}
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
if it.args.len > 0 {
|
if it.args.len > 0 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
g.call_args(it.args)
|
g.call_args(it.args, it.muts)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
ast.None {
|
ast.None {
|
||||||
|
@ -643,9 +691,13 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(it.op.str())
|
g.write(it.op.str())
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
g.write(it.op.str())
|
if it.op == .amp {
|
||||||
|
g.is_amp = true
|
||||||
|
}
|
||||||
// g.write('/*pref*/')
|
// g.write('/*pref*/')
|
||||||
|
g.write(it.op.str())
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
g.is_amp = false
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
ast.UnaryExpr {
|
ast.UnaryExpr {
|
||||||
|
@ -677,13 +729,22 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
styp := g.typ(it.typ)
|
styp := g.typ(it.typ)
|
||||||
|
if g.is_amp {
|
||||||
|
g.out.go_back(1) // delete the & already generated in `prefix_expr()
|
||||||
|
g.write('($styp*)memdup(&($styp){')
|
||||||
|
}
|
||||||
|
else {
|
||||||
g.writeln('($styp){')
|
g.writeln('($styp){')
|
||||||
|
}
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t.$field = ')
|
g.write('\t.$field = ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
g.writeln(', ')
|
g.writeln(', ')
|
||||||
}
|
}
|
||||||
g.write('}')
|
g.write('}')
|
||||||
|
if g.is_amp {
|
||||||
|
g.write(', sizeof($styp))')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
|
@ -731,14 +792,27 @@ fn (g mut Gen) infix_expr(it ast.InfixExpr) {
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
// arr << val
|
else if it.op == .key_in {
|
||||||
else if it.op == .left_shift && g.table.get_type_symbol(it.left_type).kind == .array {
|
styp := g.typ(it.left_type)
|
||||||
g.write('array_push(')
|
g.write('_IN($styp, ')
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
// arr << val
|
||||||
|
else if it.op == .left_shift && g.table.get_type_symbol(it.left_type).kind == .array {
|
||||||
|
sym := g.table.get_type_symbol(it.left_type)
|
||||||
|
info := sym.info as table.Array
|
||||||
|
elem_type_str := g.typ(info.elem_type)
|
||||||
|
// g.write('array_push(&')
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
g.write('_PUSH(&')
|
||||||
|
g.expr(it.left)
|
||||||
|
g.write(', ')
|
||||||
|
g.expr(it.right)
|
||||||
|
g.write(', $tmp, $elem_type_str)')
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// if it.op == .dot {
|
// if it.op == .dot {
|
||||||
// println('!! dot')
|
// println('!! dot')
|
||||||
|
@ -847,8 +921,11 @@ fn (g mut Gen) const_decl(node ast.ConstDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) call_args(args []ast.Expr) {
|
fn (g mut Gen) call_args(args []ast.Expr, muts []bool) {
|
||||||
for i, expr in args {
|
for i, expr in args {
|
||||||
|
if muts[i] {
|
||||||
|
g.write('&/*mut*/')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if i != args.len - 1 {
|
if i != args.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
@ -860,19 +937,26 @@ fn verror(s string) {
|
||||||
println('cgen error: $s')
|
println('cgen error: $s')
|
||||||
// exit(1)
|
// exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
builtins = ['string', 'array', 'KeyValue', 'map', 'Option']
|
||||||
|
)
|
||||||
|
|
||||||
|
fn (g mut Gen) write_builtin_types() {
|
||||||
|
mut builtin_types := []table.TypeSymbol // builtin types
|
||||||
|
// builtin types need to be on top
|
||||||
|
// everything except builtin will get sorted
|
||||||
|
for builtin_name in builtins {
|
||||||
|
builtin_types << g.table.types[g.table.type_idxs[builtin_name]]
|
||||||
|
}
|
||||||
|
g.write_types(builtin_types)
|
||||||
|
}
|
||||||
|
|
||||||
// C struct definitions, ordered
|
// C struct definitions, ordered
|
||||||
// Sort the types, make sure types that are referenced by other types
|
// Sort the types, make sure types that are referenced by other types
|
||||||
// are added before them.
|
// are added before them.
|
||||||
fn (g mut Gen) write_sorted_types() {
|
fn (g mut Gen) write_sorted_types() {
|
||||||
mut types := []table.TypeSymbol // structs that need to be sorted
|
mut types := []table.TypeSymbol // structs that need to be sorted
|
||||||
// builtin_types := [
|
|
||||||
mut builtin_types := []table.TypeSymbol // builtin types
|
|
||||||
// builtin types need to be on top
|
|
||||||
builtins := ['string', 'array', 'KeyValue', 'map', 'Option']
|
|
||||||
// everything except builtin will get sorted
|
|
||||||
for builtin_name in builtins {
|
|
||||||
builtin_types << g.table.types[g.table.type_idxs[builtin_name]]
|
|
||||||
}
|
|
||||||
for typ in g.table.types {
|
for typ in g.table.types {
|
||||||
if !(typ.name in builtins) {
|
if !(typ.name in builtins) {
|
||||||
types << typ
|
types << typ
|
||||||
|
@ -882,7 +966,7 @@ fn (g mut Gen) write_sorted_types() {
|
||||||
types_sorted := g.sort_structs(types)
|
types_sorted := g.sort_structs(types)
|
||||||
// Generate C code
|
// Generate C code
|
||||||
g.definitions.writeln('// builtin types:')
|
g.definitions.writeln('// builtin types:')
|
||||||
g.write_types(builtin_types)
|
// g.write_types(builtin_types)
|
||||||
g.definitions.writeln('//------------------ #endbuiltin')
|
g.definitions.writeln('//------------------ #endbuiltin')
|
||||||
g.write_types(types_sorted)
|
g.write_types(types_sorted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,14 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nr_tests = 4
|
nr_tests = 4
|
||||||
|
term_ok = term.ok_message('OK')
|
||||||
|
term_fail = term.fail_message('FAIL')
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_c_files() {
|
fn test_c_files() {
|
||||||
println('Running V => C tests')
|
println('Running V => C tests')
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
vroot := os.dir(vexe)
|
vroot := os.dir(vexe)
|
||||||
term_ok := term.ok_message('OK')
|
|
||||||
term_fail := term.fail_message('FAIL')
|
|
||||||
for i in 1 .. (nr_tests + 1) {
|
for i in 1 .. (nr_tests + 1) {
|
||||||
path := '$vroot/vlib/v/gen/tests/${i}.vv'
|
path := '$vroot/vlib/v/gen/tests/${i}.vv'
|
||||||
mut ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
mut ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or {
|
||||||
|
@ -24,30 +24,31 @@ fn test_c_files() {
|
||||||
mut b := builder.new_builder(pref.Preferences{})
|
mut b := builder.new_builder(pref.Preferences{})
|
||||||
b.module_search_paths = ['$vroot/vlib/v/gen/tests/']
|
b.module_search_paths = ['$vroot/vlib/v/gen/tests/']
|
||||||
res := b.gen_c([path]).after('#endbuiltin')
|
res := b.gen_c([path]).after('#endbuiltin')
|
||||||
if compare_texts(res, ctext) {
|
if compare_texts(res, ctext, path) {
|
||||||
eprintln('${term_ok} ${i}')
|
println('${term_ok} ${i}')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eprintln('${term_fail} ${i}')
|
|
||||||
eprintln('${path}: got\n$res')
|
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare_texts(a, b string) bool {
|
fn compare_texts(a, b, path string) bool {
|
||||||
lines_a_ := a.trim_space().split_into_lines()
|
lines_a_ := a.trim_space().split_into_lines()
|
||||||
lines_b_ := b.trim_space().split_into_lines()
|
lines_b_ := b.trim_space().split_into_lines()
|
||||||
lines_a := lines_a_.filter(it != '')
|
lines_a := lines_a_.filter(it != '')
|
||||||
lines_b := lines_b_.filter(it != '')
|
lines_b := lines_b_.filter(it != '')
|
||||||
if lines_a.len != lines_b.len {
|
if lines_a.len != lines_b.len {
|
||||||
println(term.red('different len'))
|
println(term.red('different len'))
|
||||||
// return false
|
println('${path}: got\n$a')
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
for i, line_a in lines_a {
|
for i, line_a in lines_a {
|
||||||
line_b := lines_b[i]
|
line_b := lines_b[i]
|
||||||
if line_a.trim_space() != line_b.trim_space() {
|
if line_a.trim_space() != line_b.trim_space() {
|
||||||
println(term.red('i=$i V="$line_a" C="$line_b"'))
|
println('${path}: got\n$a')
|
||||||
|
println('${term_fail} ${i}')
|
||||||
|
println(term.red('i=$i "$line_a" expected="$line_b"'))
|
||||||
// exit(1)
|
// exit(1)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,6 +294,7 @@ typedef array array_u32;
|
||||||
typedef array array_u64;
|
typedef array array_u64;
|
||||||
typedef map map_int;
|
typedef map map_int;
|
||||||
typedef map map_string;
|
typedef map map_string;
|
||||||
|
typedef byte array_fixed_byte_300 [300];
|
||||||
#ifndef bool
|
#ifndef bool
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
#define true 1
|
#define true 1
|
||||||
|
|
|
@ -52,7 +52,9 @@ int main() {
|
||||||
localmod__pub_foo();
|
localmod__pub_foo();
|
||||||
int ten = localmod__get_int_10();
|
int ten = localmod__get_int_10();
|
||||||
println(localmod__pub_int_const);
|
println(localmod__pub_int_const);
|
||||||
int g = (int)(3.0);
|
int g = ((int)(3.0));
|
||||||
|
byte* bytes = ((byte*)(0));
|
||||||
|
User user_ptr = (User*)memdup(&(User){}, sizeof(User));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ fn main() {
|
||||||
ten := localmod.get_int_10()
|
ten := localmod.get_int_10()
|
||||||
println(localmod.pub_int_const)
|
println(localmod.pub_int_const)
|
||||||
g := int(3.0)
|
g := int(3.0)
|
||||||
|
bytes := &byte(0)
|
||||||
|
user_ptr := &User{}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
user := User{}
|
user := User{}
|
||||||
|
|
|
@ -75,6 +75,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
mut is_method := false
|
mut is_method := false
|
||||||
mut rec_type := table.void_type
|
mut rec_type := table.void_type
|
||||||
mut rec_mut := false
|
mut rec_mut := false
|
||||||
|
mut args := []table.Var
|
||||||
|
mut ast_args := []ast.Arg
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
is_method = true
|
is_method = true
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -84,6 +86,15 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
rec_mut = true
|
rec_mut = true
|
||||||
}
|
}
|
||||||
rec_type = p.parse_type()
|
rec_type = p.parse_type()
|
||||||
|
args << table.Var{
|
||||||
|
// Receiver is the first arg
|
||||||
|
typ: rec_type
|
||||||
|
name: rec_name
|
||||||
|
}
|
||||||
|
ast_args << ast.Arg{
|
||||||
|
name: rec_name
|
||||||
|
typ: rec_type
|
||||||
|
}
|
||||||
// p.table.register_var(table.Var{
|
// p.table.register_var(table.Var{
|
||||||
// name: rec_name
|
// name: rec_name
|
||||||
// typ: rec_type
|
// typ: rec_type
|
||||||
|
@ -111,8 +122,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
// println('fn decl $name')
|
// println('fn decl $name')
|
||||||
// Args
|
// Args
|
||||||
mut args := []table.Var
|
ast_args2,is_variadic := p.fn_args()
|
||||||
ast_args,is_variadic := p.fn_args()
|
ast_args << ast_args2
|
||||||
for ast_arg in ast_args {
|
for ast_arg in ast_args {
|
||||||
var := table.Var{
|
var := table.Var{
|
||||||
name: ast_arg.name
|
name: ast_arg.name
|
||||||
|
|
|
@ -44,6 +44,7 @@ mut:
|
||||||
scope &ast.Scope
|
scope &ast.Scope
|
||||||
imports map[string]string
|
imports map[string]string
|
||||||
ast_imports []ast.Import
|
ast_imports []ast.Import
|
||||||
|
is_amp bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
|
@ -558,7 +559,11 @@ pub fn (p mut Parser) name_expr() ast.Expr {
|
||||||
// if name in table.builtin_type_names {
|
// if name in table.builtin_type_names {
|
||||||
if (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) && !(name in ['C.stat', 'C.sigaction']) {
|
if (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) && !(name in ['C.stat', 'C.sigaction']) {
|
||||||
// TODO handle C.stat()
|
// TODO handle C.stat()
|
||||||
to_typ := p.parse_type()
|
mut to_typ := p.parse_type()
|
||||||
|
if p.is_amp {
|
||||||
|
// Handle `&Foo(0)`
|
||||||
|
to_typ = table.type_to_ptr(to_typ)
|
||||||
|
}
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut expr := ast.Expr{}
|
mut expr := ast.Expr{}
|
||||||
mut arg := ast.Expr{}
|
mut arg := ast.Expr{}
|
||||||
|
@ -810,8 +815,12 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||||
|
|
||||||
fn (p mut Parser) prefix_expr() ast.PrefixExpr {
|
fn (p mut Parser) prefix_expr() ast.PrefixExpr {
|
||||||
op := p.tok.kind
|
op := p.tok.kind
|
||||||
|
if op == .amp {
|
||||||
|
p.is_amp = true
|
||||||
|
}
|
||||||
p.next()
|
p.next()
|
||||||
right := p.expr(1)
|
right := p.expr(1)
|
||||||
|
p.is_amp = false
|
||||||
return ast.PrefixExpr{
|
return ast.PrefixExpr{
|
||||||
op: op
|
op: op
|
||||||
right: right
|
right: right
|
||||||
|
@ -1715,7 +1724,6 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
|
||||||
sub_types: sum_variants
|
sub_types: sum_variants
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// type MyType int
|
// type MyType int
|
||||||
parent_type := p.parse_type()
|
parent_type := p.parse_type()
|
||||||
pid := table.type_idx(parent_type)
|
pid := table.type_idx(parent_type)
|
||||||
|
|
Loading…
Reference in New Issue