mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: lots of fixes
This commit is contained in:
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
|
||||
pub fn (a array) clone() array {
|
||||
pub fn (a &array) clone() array {
|
||||
mut size := a.cap * a.element_size
|
||||
if size == 0 {
|
||||
size++
|
||||
@ -270,7 +270,7 @@ pub fn (a array) clone() array {
|
||||
return arr
|
||||
}
|
||||
|
||||
fn (a array) slice_clone(start, _end int) array {
|
||||
fn (a &array) slice_clone(start, _end int) array {
|
||||
mut end := _end
|
||||
$if !no_bounds_checking? {
|
||||
if start > end {
|
||||
@ -316,8 +316,6 @@ pub fn (a3 mut array) push_many(val voidptr, size int) {
|
||||
// handle `arr << arr`
|
||||
copy := a3.clone()
|
||||
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(a3.data + a3.element_size * a3.len, copy.data, a3.element_size * size)
|
||||
} else {
|
||||
|
@ -190,7 +190,7 @@ pub fn (c rune) str() string {
|
||||
for i in 0..len {
|
||||
str.str[i] = int(c)>>8 * (3 - i) & 0xff
|
||||
}
|
||||
str[len] = `\0`
|
||||
str.str[len] = `\0`
|
||||
return str
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,11 @@ pub fn (b mut Builder) write(s string) {
|
||||
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) {
|
||||
// for c in s {
|
||||
// b.buf << c
|
||||
|
@ -10,15 +10,15 @@ import (
|
||||
|
||||
pub type TypeDecl = AliasTypeDecl | SumTypeDecl
|
||||
|
||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
|
||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
|
||||
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
|
||||
CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr |
|
||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
|
||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
|
||||
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
|
||||
CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr |
|
||||
ConcatExpr | Type | AsCast
|
||||
|
||||
pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
|
||||
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
|
||||
HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt |
|
||||
pub type Stmt = GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
|
||||
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
|
||||
HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt |
|
||||
LineComment | MultiLineComment | AssertStmt | UnsafeStmt
|
||||
// pub type Type = StructType | ArrayType
|
||||
// pub struct StructType {
|
||||
@ -156,28 +156,31 @@ pub:
|
||||
pub struct CallExpr {
|
||||
pub:
|
||||
// tok token.Token
|
||||
pos token.Position
|
||||
pos token.Position
|
||||
mut:
|
||||
// func Expr
|
||||
name string
|
||||
args []Expr
|
||||
is_c bool
|
||||
muts []bool
|
||||
or_block OrExpr
|
||||
name string
|
||||
args []Expr
|
||||
arg_types []table.Type
|
||||
is_c bool
|
||||
muts []bool
|
||||
or_block OrExpr
|
||||
typ table.Type
|
||||
}
|
||||
|
||||
pub struct MethodCallExpr {
|
||||
pub:
|
||||
// tok token.Token
|
||||
pos token.Position
|
||||
expr Expr
|
||||
name string
|
||||
args []Expr
|
||||
muts []bool
|
||||
or_block OrExpr
|
||||
pos token.Position
|
||||
expr Expr // `user` in `user.register()`
|
||||
name string
|
||||
args []Expr
|
||||
muts []bool
|
||||
or_block OrExpr
|
||||
mut:
|
||||
typ table.Type
|
||||
expr_type table.Type // type of `user`
|
||||
receiver_type table.Type // User
|
||||
typ table.Type
|
||||
}
|
||||
|
||||
pub struct Return {
|
||||
|
@ -22,6 +22,7 @@ mut:
|
||||
errors []string
|
||||
expected_type table.Type
|
||||
fn_return_type table.Type // current function's return type
|
||||
// is_amp bool
|
||||
}
|
||||
|
||||
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
|
||||
pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) table.Type {
|
||||
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)
|
||||
name := method_call_expr.name
|
||||
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
|
||||
}
|
||||
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 {
|
||||
c.expected_type = method.args[i].typ
|
||||
c.expr(arg_expr)
|
||||
@ -382,7 +387,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
||||
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
||||
for i, _ in assign_stmt.left {
|
||||
mut ident := assign_stmt.left[i]
|
||||
val_type := mr_info.types[i]
|
||||
val_type := mr_info.types[i]
|
||||
mut var_info := ident.var_info()
|
||||
var_info.typ = val_type
|
||||
ident.info = var_info
|
||||
@ -403,7 +408,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
||||
}
|
||||
// `a := 1` | `a,b := 1,2`
|
||||
else {
|
||||
if assign_stmt.left.len != assign_stmt.right.len {
|
||||
if assign_stmt.left.len != assign_stmt.right.len {
|
||||
c.error('wrong number of vars', assign_stmt.pos)
|
||||
}
|
||||
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
||||
|
@ -19,6 +19,7 @@ mut:
|
||||
is_c_call bool // e.g. `C.printf("v")`
|
||||
is_assign_expr 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 {
|
||||
@ -42,6 +43,7 @@ pub fn (g mut Gen) init() {
|
||||
g.definitions.writeln('#include <inttypes.h>') // int64_t etc
|
||||
g.definitions.writeln(c_builtin_types)
|
||||
g.definitions.writeln(c_headers)
|
||||
g.write_builtin_types()
|
||||
g.write_array_types()
|
||||
g.write_sorted_types()
|
||||
g.write_multi_return_types()
|
||||
@ -211,7 +213,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
}
|
||||
ast.ForStmt {
|
||||
g.write('while (')
|
||||
g.expr(it.cond)
|
||||
if it.is_inf {
|
||||
g.write('1')
|
||||
}
|
||||
else {
|
||||
g.expr(it.cond)
|
||||
}
|
||||
g.writeln(') {')
|
||||
for stmt in it.stmts {
|
||||
g.stmt(stmt)
|
||||
@ -288,20 +295,20 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
else {
|
||||
panic('expected call')
|
||||
}
|
||||
}
|
||||
mr_typ_sym := g.table.get_type_symbol(return_type)
|
||||
}
|
||||
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.writeln(';')
|
||||
for i, ident in assign_stmt.left {
|
||||
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 {
|
||||
g.writeln('{$var_type_sym.name _ = $mr_var_name->arg[$i]};')
|
||||
g.writeln('{ $styp _ = ${mr_var_name}.arg$i};')
|
||||
}
|
||||
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 {
|
||||
val := assign_stmt.right[i]
|
||||
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 {
|
||||
is_call := match val {
|
||||
ast.CallExpr { true }
|
||||
ast.MethodCallExpr { true }
|
||||
else { false }
|
||||
}
|
||||
ast.CallExpr{
|
||||
true
|
||||
}
|
||||
ast.MethodCallExpr{
|
||||
true
|
||||
}
|
||||
else {
|
||||
false}
|
||||
}
|
||||
if is_call {
|
||||
g.expr(val)
|
||||
g.expr(val)
|
||||
}
|
||||
else {
|
||||
g.write('{$var_type_sym.name _ = ')
|
||||
g.write('{$styp _ = ')
|
||||
g.expr(val)
|
||||
g.write('}')
|
||||
g.write('}')
|
||||
}
|
||||
}
|
||||
else {
|
||||
g.write('$var_type_sym.name $ident.name = ')
|
||||
g.write('$styp $ident.name = ')
|
||||
g.expr(val)
|
||||
}
|
||||
g.writeln(';')
|
||||
@ -359,13 +371,14 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||
g.definitions.write('$type_name ${name}(')
|
||||
}
|
||||
// Receiver is the first argument
|
||||
/*
|
||||
if it.is_method {
|
||||
mut styp := g.typ(it.receiver.typ)
|
||||
// if table.type_nr_muls(it.receiver.typ) > 0 {
|
||||
// if it.rec_mut {
|
||||
// styp += '*'
|
||||
// }
|
||||
g.write('$styp $it.receiver.name')
|
||||
g.write('$styp $it.receiver.name ')
|
||||
// TODO mut
|
||||
g.definitions.write('$styp $it.receiver.name')
|
||||
if it.args.len > 0 {
|
||||
@ -373,6 +386,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||
g.definitions.write(', ')
|
||||
}
|
||||
}
|
||||
*/
|
||||
//
|
||||
no_names := it.args.len > 0 && it.args[0].name == 'arg_1'
|
||||
for i, arg in it.args {
|
||||
@ -459,13 +473,24 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
name = name[3..]
|
||||
}
|
||||
g.write('${name}(')
|
||||
g.call_args(it.args)
|
||||
g.call_args(it.args, it.muts)
|
||||
g.write(')')
|
||||
g.is_c_call = false
|
||||
}
|
||||
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 {
|
||||
g.write('tos(')
|
||||
// tos(str, len), tos2(str)
|
||||
if it.has_arg {
|
||||
g.write('tos(')
|
||||
}
|
||||
else {
|
||||
g.write('tos2(')
|
||||
}
|
||||
g.expr(it.expr)
|
||||
if it.has_arg {
|
||||
g.write(',')
|
||||
@ -474,10 +499,16 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
g.write(')')
|
||||
}
|
||||
else {
|
||||
styp := g.table.type_to_str(it.typ)
|
||||
g.write('($styp)(')
|
||||
// styp := g.table.type_to_str(it.typ)
|
||||
styp := g.typ(it.typ)
|
||||
// g.write('($styp)(')
|
||||
g.write('(($styp)(')
|
||||
// if g.is_amp {
|
||||
// g.write('*')
|
||||
// }
|
||||
// g.write(')(')
|
||||
g.expr(it.expr)
|
||||
g.write(')')
|
||||
g.write('))')
|
||||
}
|
||||
}
|
||||
ast.CharLiteral {
|
||||
@ -491,7 +522,12 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
}
|
||||
ast.Ident {
|
||||
name := it.name.replace('.', '__')
|
||||
g.write(name)
|
||||
if name.starts_with('C__') {
|
||||
g.write(name[3..])
|
||||
}
|
||||
else {
|
||||
g.write(name)
|
||||
}
|
||||
}
|
||||
ast.IfExpr {
|
||||
// If expression? Assign the value to a temp var.
|
||||
@ -544,9 +580,11 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
g.write('/* guard */')
|
||||
}
|
||||
ast.IndexExpr {
|
||||
//
|
||||
g.index_expr(it)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
// sdf
|
||||
g.infix_expr(it)
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
@ -614,20 +652,30 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
ast.MethodCallExpr {
|
||||
mut receiver_name := 'TODO'
|
||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||
if it.typ != 0 {
|
||||
typ_sym := g.table.get_type_symbol(it.typ)
|
||||
if it.expr_type != 0 {
|
||||
typ_sym := g.table.get_type_symbol(it.expr_type)
|
||||
receiver_name = typ_sym.name
|
||||
// if typ_sym.kind == .array {
|
||||
// receiver_name = 'array'
|
||||
// }
|
||||
if typ_sym.kind == .array && receiver_name.starts_with('array_') {
|
||||
// array_byte_clone => array_clone
|
||||
receiver_name = 'array'
|
||||
}
|
||||
}
|
||||
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}(')
|
||||
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)
|
||||
if it.args.len > 0 {
|
||||
g.write(', ')
|
||||
}
|
||||
g.call_args(it.args)
|
||||
g.call_args(it.args, it.muts)
|
||||
g.write(')')
|
||||
}
|
||||
ast.None {
|
||||
@ -643,9 +691,13 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
g.write(it.op.str())
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
g.write(it.op.str())
|
||||
if it.op == .amp {
|
||||
g.is_amp = true
|
||||
}
|
||||
// g.write('/*pref*/')
|
||||
g.write(it.op.str())
|
||||
g.expr(it.right)
|
||||
g.is_amp = false
|
||||
}
|
||||
/*
|
||||
ast.UnaryExpr {
|
||||
@ -677,13 +729,22 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
styp := g.typ(it.typ)
|
||||
g.writeln('($styp){')
|
||||
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){')
|
||||
}
|
||||
for i, field in it.fields {
|
||||
g.write('\t.$field = ')
|
||||
g.expr(it.exprs[i])
|
||||
g.writeln(', ')
|
||||
}
|
||||
g.write('}')
|
||||
if g.is_amp {
|
||||
g.write(', sizeof($styp))')
|
||||
}
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
g.expr(it.expr)
|
||||
@ -731,14 +792,27 @@ fn (g mut Gen) infix_expr(it ast.InfixExpr) {
|
||||
g.expr(it.right)
|
||||
g.write(')')
|
||||
}
|
||||
// arr << val
|
||||
else if it.op == .left_shift && g.table.get_type_symbol(it.left_type).kind == .array {
|
||||
g.write('array_push(')
|
||||
else if it.op == .key_in {
|
||||
styp := g.typ(it.left_type)
|
||||
g.write('_IN($styp, ')
|
||||
g.expr(it.left)
|
||||
g.write(', ')
|
||||
g.expr(it.right)
|
||||
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 {
|
||||
// if it.op == .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 {
|
||||
if muts[i] {
|
||||
g.write('&/*mut*/')
|
||||
}
|
||||
g.expr(expr)
|
||||
if i != args.len - 1 {
|
||||
g.write(', ')
|
||||
@ -860,19 +937,26 @@ fn verror(s string) {
|
||||
println('cgen error: $s')
|
||||
// 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
|
||||
// Sort the types, make sure types that are referenced by other types
|
||||
// are added before them.
|
||||
fn (g mut Gen) write_sorted_types() {
|
||||
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 {
|
||||
if !(typ.name in builtins) {
|
||||
types << typ
|
||||
@ -882,7 +966,7 @@ fn (g mut Gen) write_sorted_types() {
|
||||
types_sorted := g.sort_structs(types)
|
||||
// Generate C code
|
||||
g.definitions.writeln('// builtin types:')
|
||||
g.write_types(builtin_types)
|
||||
// g.write_types(builtin_types)
|
||||
g.definitions.writeln('//------------------ #endbuiltin')
|
||||
g.write_types(types_sorted)
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ import (
|
||||
|
||||
const (
|
||||
nr_tests = 4
|
||||
term_ok = term.ok_message('OK')
|
||||
term_fail = term.fail_message('FAIL')
|
||||
)
|
||||
|
||||
fn test_c_files() {
|
||||
println('Running V => C tests')
|
||||
vexe := os.getenv('VEXE')
|
||||
vroot := os.dir(vexe)
|
||||
term_ok := term.ok_message('OK')
|
||||
term_fail := term.fail_message('FAIL')
|
||||
for i in 1 .. (nr_tests + 1) {
|
||||
path := '$vroot/vlib/v/gen/tests/${i}.vv'
|
||||
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{})
|
||||
b.module_search_paths = ['$vroot/vlib/v/gen/tests/']
|
||||
res := b.gen_c([path]).after('#endbuiltin')
|
||||
if compare_texts(res, ctext) {
|
||||
eprintln('${term_ok} ${i}')
|
||||
if compare_texts(res, ctext, path) {
|
||||
println('${term_ok} ${i}')
|
||||
}
|
||||
else {
|
||||
eprintln('${term_fail} ${i}')
|
||||
eprintln('${path}: got\n$res')
|
||||
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_b_ := b.trim_space().split_into_lines()
|
||||
lines_a := lines_a_.filter(it != '')
|
||||
lines_b := lines_b_.filter(it != '')
|
||||
if lines_a.len != lines_b.len {
|
||||
println(term.red('different len'))
|
||||
// return false
|
||||
println('${path}: got\n$a')
|
||||
return false
|
||||
}
|
||||
for i, line_a in lines_a {
|
||||
line_b := lines_b[i]
|
||||
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)
|
||||
return false
|
||||
}
|
||||
|
@ -294,6 +294,7 @@ typedef array array_u32;
|
||||
typedef array array_u64;
|
||||
typedef map map_int;
|
||||
typedef map map_string;
|
||||
typedef byte array_fixed_byte_300 [300];
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
|
@ -52,7 +52,9 @@ int main() {
|
||||
localmod__pub_foo();
|
||||
int ten = localmod__get_int_10();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,8 @@ fn main() {
|
||||
ten := localmod.get_int_10()
|
||||
println(localmod.pub_int_const)
|
||||
g := int(3.0)
|
||||
bytes := &byte(0)
|
||||
user_ptr := &User{}
|
||||
}
|
||||
/*
|
||||
user := User{}
|
||||
|
@ -75,6 +75,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
mut is_method := false
|
||||
mut rec_type := table.void_type
|
||||
mut rec_mut := false
|
||||
mut args := []table.Var
|
||||
mut ast_args := []ast.Arg
|
||||
if p.tok.kind == .lpar {
|
||||
is_method = true
|
||||
p.next()
|
||||
@ -84,6 +86,15 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
rec_mut = true
|
||||
}
|
||||
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{
|
||||
// name: rec_name
|
||||
// typ: rec_type
|
||||
@ -111,8 +122,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
}
|
||||
// println('fn decl $name')
|
||||
// Args
|
||||
mut args := []table.Var
|
||||
ast_args,is_variadic := p.fn_args()
|
||||
ast_args2,is_variadic := p.fn_args()
|
||||
ast_args << ast_args2
|
||||
for ast_arg in ast_args {
|
||||
var := table.Var{
|
||||
name: ast_arg.name
|
||||
|
@ -44,6 +44,7 @@ mut:
|
||||
scope &ast.Scope
|
||||
imports map[string]string
|
||||
ast_imports []ast.Import
|
||||
is_amp bool
|
||||
}
|
||||
|
||||
// for tests
|
||||
@ -55,7 +56,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
|
||||
pref: &pref.Preferences{}
|
||||
scope: scope
|
||||
// scope: &ast.Scope{start_pos: 0, parent: 0}
|
||||
|
||||
|
||||
}
|
||||
p.init_parse_fns()
|
||||
p.read_first_token()
|
||||
@ -79,7 +80,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
|
||||
parent: 0
|
||||
}
|
||||
// comments_mode: comments_mode
|
||||
|
||||
|
||||
}
|
||||
p.read_first_token()
|
||||
// p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0}
|
||||
@ -558,7 +559,11 @@ pub fn (p mut Parser) name_expr() ast.Expr {
|
||||
// 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']) {
|
||||
// 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)
|
||||
mut expr := ast.Expr{}
|
||||
mut arg := ast.Expr{}
|
||||
@ -613,7 +618,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
|
||||
p.expr_mod = ''
|
||||
return ast.EnumVal{
|
||||
enum_name: enum_name // lp.prepend_mod(enum_name)
|
||||
|
||||
|
||||
val: val
|
||||
pos: p.tok.position()
|
||||
}
|
||||
@ -810,8 +815,12 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
||||
|
||||
fn (p mut Parser) prefix_expr() ast.PrefixExpr {
|
||||
op := p.tok.kind
|
||||
if op == .amp {
|
||||
p.is_amp = true
|
||||
}
|
||||
p.next()
|
||||
right := p.expr(1)
|
||||
p.is_amp = false
|
||||
return ast.PrefixExpr{
|
||||
op: op
|
||||
right: right
|
||||
@ -940,7 +949,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
left: left
|
||||
right: right
|
||||
// right_type: typ
|
||||
|
||||
|
||||
op: op
|
||||
pos: pos
|
||||
}
|
||||
@ -1051,7 +1060,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||
p.scope.register_var(ast.Var{
|
||||
name: var_name
|
||||
// expr: cond
|
||||
|
||||
|
||||
})
|
||||
stmts := p.parse_block()
|
||||
// println('nr stmts=$stmts.len')
|
||||
@ -1146,11 +1155,11 @@ fn (p mut Parser) if_expr() ast.Expr {
|
||||
stmts: stmts
|
||||
else_stmts: else_stmts
|
||||
// typ: typ
|
||||
|
||||
|
||||
pos: pos
|
||||
has_else: has_else
|
||||
// left: left
|
||||
|
||||
|
||||
}
|
||||
return node
|
||||
}
|
||||
@ -1324,7 +1333,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
|
||||
fields << ast.Field{
|
||||
name: name
|
||||
// typ: typ
|
||||
|
||||
|
||||
}
|
||||
exprs << expr
|
||||
// TODO: once consts are fixed reg here & update in checker
|
||||
@ -1715,7 +1724,6 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
|
||||
sub_types: sum_variants
|
||||
}
|
||||
}
|
||||
|
||||
// type MyType int
|
||||
parent_type := p.parse_type()
|
||||
pid := table.type_idx(parent_type)
|
||||
|
Loading…
Reference in New Issue
Block a user