cgen: `go xxx()`
parent
6a5cc0fa19
commit
52f096f5d9
|
@ -187,7 +187,7 @@ pub:
|
|||
mut:
|
||||
name string
|
||||
args []CallArg
|
||||
exp_arg_types []table.Type
|
||||
expected_arg_types []table.Type
|
||||
is_c bool
|
||||
or_block OrExpr
|
||||
// has_or_block bool
|
||||
|
@ -546,7 +546,7 @@ mut:
|
|||
|
||||
pub struct GoStmt {
|
||||
pub:
|
||||
expr Expr
|
||||
call_expr Expr
|
||||
}
|
||||
|
||||
pub struct GotoLabel {
|
||||
|
|
|
@ -238,9 +238,9 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
|||
call_expr.args[i].typ = c.expr(arg.expr)
|
||||
}
|
||||
// TODO: typ optimize.. this node can get processed more than once
|
||||
if call_expr.exp_arg_types.len == 0 {
|
||||
if call_expr.expected_arg_types.len == 0 {
|
||||
for i in 1 .. method.args.len {
|
||||
call_expr.exp_arg_types << method.args[i].typ
|
||||
call_expr.expected_arg_types << method.args[i].typ
|
||||
}
|
||||
}
|
||||
call_expr.receiver_type = method.args[0].typ
|
||||
|
@ -337,9 +337,9 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
|||
return f.return_type
|
||||
}
|
||||
// TODO: typ optimize.. this node can get processed more than once
|
||||
if call_expr.exp_arg_types.len == 0 {
|
||||
if call_expr.expected_arg_types.len == 0 {
|
||||
for arg in f.args {
|
||||
call_expr.exp_arg_types << arg.typ
|
||||
call_expr.expected_arg_types << arg.typ
|
||||
}
|
||||
}
|
||||
for i, call_arg in call_expr.args {
|
||||
|
@ -694,6 +694,9 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
ast.GoStmt{
|
||||
c.expr(it.call_expr)
|
||||
}
|
||||
// ast.GlobalDecl {}
|
||||
// ast.HashStmt {}
|
||||
ast.Import {}
|
||||
|
|
|
@ -49,6 +49,7 @@ mut:
|
|||
defer_stmts []ast.DeferStmt
|
||||
defer_ifdef string
|
||||
str_types []int // types that need automatic str() generation
|
||||
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -392,8 +393,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
g.definitions.writeln('$styp $it.name; // global')
|
||||
}
|
||||
ast.GoStmt {
|
||||
g.writeln('// go')
|
||||
g.expr(it.expr)
|
||||
g.go_stmt(it)
|
||||
}
|
||||
ast.GotoLabel {
|
||||
g.writeln('$it.name:')
|
||||
|
@ -2369,7 +2369,8 @@ fn (g mut Gen) method_call(node ast.CallExpr) {
|
|||
g.write('/*rec*/*')
|
||||
}
|
||||
g.expr(node.left)
|
||||
is_variadic := node.exp_arg_types.len > 0 && table.type_is_variadic(node.exp_arg_types[node.exp_arg_types.len - 1])
|
||||
is_variadic := node.expected_arg_types.len > 0 &&
|
||||
table.type_is_variadic(node.expected_arg_types[node.expected_arg_types.len - 1])
|
||||
if node.args.len > 0 || is_variadic {
|
||||
g.write(', ')
|
||||
}
|
||||
|
@ -2385,7 +2386,7 @@ fn (g mut Gen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
*/
|
||||
// ///////
|
||||
g.call_args(node.args, node.exp_arg_types)
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
g.write(')')
|
||||
// if node.or_block.stmts.len > 0 {
|
||||
// g.or_block(node.or_block.stmts, node.return_type)
|
||||
|
@ -2461,7 +2462,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
|||
}
|
||||
else {
|
||||
g.write('${name}(')
|
||||
g.call_args(node.args, node.exp_arg_types)
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
g.write(')')
|
||||
}
|
||||
// if node.or_block.stmts.len > 0 {
|
||||
|
@ -2802,3 +2803,67 @@ fn (g mut Gen) comp_if(it ast.CompIf) {
|
|||
}
|
||||
g.writeln('#endif')
|
||||
}
|
||||
|
||||
fn (g mut Gen) go_stmt(node ast.GoStmt) {
|
||||
tmp := g.new_tmp_var()
|
||||
// x := node.call_expr as ast.CallEpxr // TODO
|
||||
match node.call_expr {
|
||||
ast.CallExpr{
|
||||
mut name := it.name
|
||||
if it.is_method {
|
||||
receiver_sym := g.table.get_type_symbol(it.receiver_type)
|
||||
name = receiver_sym.name + '_' + name
|
||||
}
|
||||
g.writeln('// go')
|
||||
wrapper_struct_name := 'thread_arg_' + name
|
||||
g.writeln('$wrapper_struct_name *arg_$tmp = malloc(sizeof(thread_arg_$name));')
|
||||
if it.is_method {
|
||||
g.write('arg_${tmp}->arg0 = ')
|
||||
g.expr(it.left)
|
||||
g.writeln(';')
|
||||
}
|
||||
for i, arg in it.args {
|
||||
g.write('arg_${tmp}->arg${i+1} = ')
|
||||
g.expr(arg.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
g.writeln('pthread_t thread_$tmp;')
|
||||
wrapper_fn_name := name + '_thread_wrapper'
|
||||
g.writeln('pthread_create(&thread_$tmp, NULL, (void*)$wrapper_fn_name, arg_$tmp);')
|
||||
g.writeln('// endgo\n')
|
||||
// Register the wrapper type and function
|
||||
if name in g.threaded_fns {
|
||||
return
|
||||
}
|
||||
g.definitions.writeln('\ntypedef struct $wrapper_struct_name {')
|
||||
if it.is_method {
|
||||
sym := g.table.get_type_symbol(it.receiver_type)
|
||||
g.definitions.writeln('\t$sym.name arg0;')
|
||||
}
|
||||
for i, arg in it.args {
|
||||
sym := g.table.get_type_symbol(arg.typ)
|
||||
g.definitions.writeln('\t$sym.name arg${i+1};')
|
||||
}
|
||||
g.definitions.writeln('} $wrapper_struct_name;')
|
||||
g.definitions.writeln('void* ${wrapper_fn_name}($wrapper_struct_name *arg) {')
|
||||
g.definitions.write(name + '(')
|
||||
if it.is_method {
|
||||
g.definitions.write('arg->arg0')
|
||||
if it.args.len > 0 {
|
||||
g.definitions.write(', ')
|
||||
}
|
||||
}
|
||||
for i in 0..it.args.len {
|
||||
g.definitions.write('arg->arg${i+1}')
|
||||
if i < it.args.len - 1 {
|
||||
g.definitions.write(', ')
|
||||
}
|
||||
}
|
||||
|
||||
g.definitions.writeln(');\n return 0; }')
|
||||
g.threaded_fns << name
|
||||
}
|
||||
else{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -399,8 +399,18 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||
}
|
||||
.key_go {
|
||||
p.next()
|
||||
expr := p.expr(0)
|
||||
//mut call_expr := &ast.CallExpr(0) // TODO
|
||||
match expr {
|
||||
ast.CallExpr {
|
||||
//call_expr = it
|
||||
}
|
||||
else {
|
||||
p.error('expression in `go` must be a function call')
|
||||
}
|
||||
}
|
||||
return ast.GoStmt{
|
||||
expr: p.expr(0)
|
||||
call_expr: expr
|
||||
}
|
||||
}
|
||||
.key_goto {
|
||||
|
|
Loading…
Reference in New Issue