cgen: `go xxx()`
parent
6a5cc0fa19
commit
52f096f5d9
|
@ -187,7 +187,7 @@ pub:
|
||||||
mut:
|
mut:
|
||||||
name string
|
name string
|
||||||
args []CallArg
|
args []CallArg
|
||||||
exp_arg_types []table.Type
|
expected_arg_types []table.Type
|
||||||
is_c bool
|
is_c bool
|
||||||
or_block OrExpr
|
or_block OrExpr
|
||||||
// has_or_block bool
|
// has_or_block bool
|
||||||
|
@ -546,7 +546,7 @@ mut:
|
||||||
|
|
||||||
pub struct GoStmt {
|
pub struct GoStmt {
|
||||||
pub:
|
pub:
|
||||||
expr Expr
|
call_expr Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GotoLabel {
|
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)
|
call_expr.args[i].typ = c.expr(arg.expr)
|
||||||
}
|
}
|
||||||
// TODO: typ optimize.. this node can get processed more than once
|
// 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 {
|
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
|
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
|
return f.return_type
|
||||||
}
|
}
|
||||||
// TODO: typ optimize.. this node can get processed more than once
|
// 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 {
|
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 {
|
for i, call_arg in call_expr.args {
|
||||||
|
@ -694,6 +694,9 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
c.stmts(it.stmts)
|
c.stmts(it.stmts)
|
||||||
}
|
}
|
||||||
|
ast.GoStmt{
|
||||||
|
c.expr(it.call_expr)
|
||||||
|
}
|
||||||
// ast.GlobalDecl {}
|
// ast.GlobalDecl {}
|
||||||
// ast.HashStmt {}
|
// ast.HashStmt {}
|
||||||
ast.Import {}
|
ast.Import {}
|
||||||
|
|
|
@ -49,6 +49,7 @@ mut:
|
||||||
defer_stmts []ast.DeferStmt
|
defer_stmts []ast.DeferStmt
|
||||||
defer_ifdef string
|
defer_ifdef string
|
||||||
str_types []int // types that need automatic str() generation
|
str_types []int // types that need automatic str() generation
|
||||||
|
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -392,8 +393,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.definitions.writeln('$styp $it.name; // global')
|
g.definitions.writeln('$styp $it.name; // global')
|
||||||
}
|
}
|
||||||
ast.GoStmt {
|
ast.GoStmt {
|
||||||
g.writeln('// go')
|
g.go_stmt(it)
|
||||||
g.expr(it.expr)
|
|
||||||
}
|
}
|
||||||
ast.GotoLabel {
|
ast.GotoLabel {
|
||||||
g.writeln('$it.name:')
|
g.writeln('$it.name:')
|
||||||
|
@ -2369,7 +2369,8 @@ fn (g mut Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('/*rec*/*')
|
g.write('/*rec*/*')
|
||||||
}
|
}
|
||||||
g.expr(node.left)
|
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 {
|
if node.args.len > 0 || is_variadic {
|
||||||
g.write(', ')
|
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(')')
|
g.write(')')
|
||||||
// if node.or_block.stmts.len > 0 {
|
// if node.or_block.stmts.len > 0 {
|
||||||
// g.or_block(node.or_block.stmts, node.return_type)
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
@ -2461,7 +2462,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('${name}(')
|
g.write('${name}(')
|
||||||
g.call_args(node.args, node.exp_arg_types)
|
g.call_args(node.args, node.expected_arg_types)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
// if node.or_block.stmts.len > 0 {
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
@ -2802,3 +2803,67 @@ fn (g mut Gen) comp_if(it ast.CompIf) {
|
||||||
}
|
}
|
||||||
g.writeln('#endif')
|
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 {
|
.key_go {
|
||||||
p.next()
|
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{
|
return ast.GoStmt{
|
||||||
expr: p.expr(0)
|
call_expr: expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_goto {
|
.key_goto {
|
||||||
|
|
Loading…
Reference in New Issue