mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: merge GoExpr and GoStmt (#9685)
This commit is contained in:
parent
6cfd53bf57
commit
5a1a1b7c12
@ -19,8 +19,8 @@ pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr |
|
||||
|
||||
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
||||
DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
|
||||
GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module |
|
||||
NodeError | Return | SqlStmt | StructDecl | TypeDecl
|
||||
GlobalDecl | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | NodeError |
|
||||
Return | SqlStmt | StructDecl | TypeDecl
|
||||
|
||||
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update
|
||||
// the .position() token.Position methods too.
|
||||
@ -963,20 +963,12 @@ pub:
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
pub struct GoStmt {
|
||||
pub:
|
||||
pos token.Position
|
||||
pub mut:
|
||||
call_expr CallExpr
|
||||
}
|
||||
|
||||
pub struct GoExpr {
|
||||
pub:
|
||||
pos token.Position
|
||||
pub mut:
|
||||
go_stmt GoStmt
|
||||
mut:
|
||||
return_type Type
|
||||
call_expr CallExpr
|
||||
is_expr bool
|
||||
}
|
||||
|
||||
pub struct GotoLabel {
|
||||
|
@ -3539,13 +3539,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
ast.GlobalDecl {
|
||||
c.global_decl(node)
|
||||
}
|
||||
ast.GoStmt {
|
||||
c.go_stmt(mut node)
|
||||
if node.call_expr.or_block.kind != .absent {
|
||||
c.error('optional handling cannot be done in `go` call. Do it when calling `.wait()`',
|
||||
node.call_expr.or_block.pos)
|
||||
}
|
||||
}
|
||||
ast.GotoLabel {}
|
||||
ast.GotoStmt {
|
||||
if !c.inside_unsafe {
|
||||
@ -3779,8 +3772,12 @@ fn (mut c Checker) global_decl(node ast.GlobalDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) go_stmt(mut node ast.GoStmt) {
|
||||
c.call_expr(mut node.call_expr)
|
||||
fn (mut c Checker) go_expr(mut node ast.GoExpr) ast.Type {
|
||||
ret_type := c.call_expr(mut node.call_expr)
|
||||
if node.call_expr.or_block.kind != .absent {
|
||||
c.error('optional handling cannot be done in `go` call. Do it when calling `.wait()`',
|
||||
node.call_expr.or_block.pos)
|
||||
}
|
||||
// Make sure there are no mutable arguments
|
||||
for arg in node.call_expr.args {
|
||||
if arg.is_mut && !arg.typ.is_ptr() {
|
||||
@ -3793,6 +3790,7 @@ fn (mut c Checker) go_stmt(mut node ast.GoStmt) {
|
||||
c.error('method in `go` statement cannot have non-reference mutable receiver',
|
||||
node.call_expr.left.position())
|
||||
}
|
||||
return c.table.find_or_register_thread(ret_type)
|
||||
}
|
||||
|
||||
fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) {
|
||||
@ -4156,14 +4154,6 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
||||
}
|
||||
return ret_type
|
||||
}
|
||||
ast.GoExpr {
|
||||
mut ret_type := c.call_expr(mut node.go_stmt.call_expr)
|
||||
if node.go_stmt.call_expr.or_block.kind != .absent {
|
||||
c.error('optional handling cannot be done in `go` call. Do it when calling `.wait()`',
|
||||
node.go_stmt.call_expr.or_block.pos)
|
||||
}
|
||||
return c.table.find_or_register_thread(ret_type)
|
||||
}
|
||||
ast.ChanInit {
|
||||
return c.chan_init(mut node)
|
||||
}
|
||||
@ -4226,6 +4216,9 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
||||
ast.FloatLiteral {
|
||||
return ast.float_literal_type
|
||||
}
|
||||
ast.GoExpr {
|
||||
return c.go_expr(mut node)
|
||||
}
|
||||
ast.Ident {
|
||||
// c.checked_ident = node.name
|
||||
res := c.ident(mut node)
|
||||
|
@ -428,9 +428,6 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||
ast.GlobalDecl {
|
||||
f.global_decl(node)
|
||||
}
|
||||
ast.GoStmt {
|
||||
f.go_stmt(node, false)
|
||||
}
|
||||
ast.GotoLabel {
|
||||
f.goto_label(node)
|
||||
}
|
||||
@ -541,7 +538,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||
f.write(node.val)
|
||||
}
|
||||
ast.GoExpr {
|
||||
f.go_stmt(node.go_stmt, true)
|
||||
f.go_expr(node)
|
||||
}
|
||||
ast.Ident {
|
||||
f.ident(node)
|
||||
@ -1130,12 +1127,9 @@ pub fn (mut f Fmt) global_decl(node ast.GlobalDecl) {
|
||||
f.writeln(')\n')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) go_stmt(node ast.GoStmt, is_expr bool) {
|
||||
pub fn (mut f Fmt) go_expr(node ast.GoExpr) {
|
||||
f.write('go ')
|
||||
f.expr(node.call_expr)
|
||||
if !is_expr {
|
||||
f.writeln('')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) goto_label(node ast.GotoLabel) {
|
||||
|
@ -1183,9 +1183,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
ast.GlobalDecl {
|
||||
g.global_decl(node)
|
||||
}
|
||||
ast.GoStmt {
|
||||
g.go_stmt(node, false)
|
||||
}
|
||||
ast.GotoLabel {
|
||||
g.writeln('$node.name: {}')
|
||||
}
|
||||
@ -5890,13 +5887,6 @@ fn (g &Gen) is_importing_os() bool {
|
||||
|
||||
fn (mut g Gen) go_expr(node ast.GoExpr) {
|
||||
line := g.go_before_stmt(0)
|
||||
handle := g.go_stmt(node.go_stmt, true)
|
||||
g.empty_line = false
|
||||
g.write(line)
|
||||
g.write(handle)
|
||||
}
|
||||
|
||||
fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||
mut handle := ''
|
||||
tmp := g.new_tmp_var()
|
||||
mut expr := node.call_expr
|
||||
@ -5966,30 +5956,30 @@ fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||
gohandle_name = '__v_thread_$opt${g.table.get_type_symbol(g.unwrap_generic(node.call_expr.return_type)).cname}'
|
||||
}
|
||||
if g.pref.os == .windows {
|
||||
simple_handle := if joinable && node.call_expr.return_type != ast.void_type {
|
||||
simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type {
|
||||
'thread_handle_$tmp'
|
||||
} else {
|
||||
'thread_$tmp'
|
||||
}
|
||||
g.writeln('HANDLE $simple_handle = CreateThread(0,0, (LPTHREAD_START_ROUTINE)$wrapper_fn_name, $arg_tmp_var, 0,0);')
|
||||
if joinable && node.call_expr.return_type != ast.void_type {
|
||||
if node.is_expr && node.call_expr.return_type != ast.void_type {
|
||||
g.writeln('$gohandle_name thread_$tmp = {')
|
||||
g.writeln('\t.ret_ptr = $arg_tmp_var->ret_ptr,')
|
||||
g.writeln('\t.handle = thread_handle_$tmp')
|
||||
g.writeln('};')
|
||||
}
|
||||
if !joinable {
|
||||
if !node.is_expr {
|
||||
g.writeln('CloseHandle(thread_$tmp);')
|
||||
}
|
||||
} else {
|
||||
g.writeln('pthread_t thread_$tmp;')
|
||||
g.writeln('pthread_create(&thread_$tmp, NULL, (void*)$wrapper_fn_name, $arg_tmp_var);')
|
||||
if !joinable {
|
||||
if !node.is_expr {
|
||||
g.writeln('pthread_detach(thread_$tmp);')
|
||||
}
|
||||
}
|
||||
g.writeln('// endgo\n')
|
||||
if joinable {
|
||||
if node.is_expr {
|
||||
handle = 'thread_$tmp'
|
||||
// create wait handler for this return type if none exists
|
||||
waiter_fn_name := gohandle_name + '_wait'
|
||||
@ -6030,63 +6020,66 @@ fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
|
||||
}
|
||||
}
|
||||
// Register the wrapper type and function
|
||||
if name in g.threaded_fns {
|
||||
return handle
|
||||
}
|
||||
g.type_definitions.writeln('\ntypedef struct $wrapper_struct_name {')
|
||||
if expr.is_method {
|
||||
styp := g.typ(expr.receiver_type)
|
||||
g.type_definitions.writeln('\t$styp arg0;')
|
||||
}
|
||||
need_return_ptr := g.pref.os == .windows && node.call_expr.return_type != ast.void_type
|
||||
if expr.args.len == 0 && !need_return_ptr {
|
||||
g.type_definitions.writeln('EMPTY_STRUCT_DECLARATION;')
|
||||
} else {
|
||||
for i, arg in expr.args {
|
||||
styp := g.typ(arg.typ)
|
||||
g.type_definitions.writeln('\t$styp arg${i + 1};')
|
||||
if name !in g.threaded_fns {
|
||||
g.type_definitions.writeln('\ntypedef struct $wrapper_struct_name {')
|
||||
if expr.is_method {
|
||||
styp := g.typ(expr.receiver_type)
|
||||
g.type_definitions.writeln('\t$styp arg0;')
|
||||
}
|
||||
}
|
||||
if need_return_ptr {
|
||||
g.type_definitions.writeln('\tvoid* ret_ptr;')
|
||||
}
|
||||
g.type_definitions.writeln('} $wrapper_struct_name;')
|
||||
thread_ret_type := if g.pref.os == .windows { 'u32' } else { 'void*' }
|
||||
g.type_definitions.writeln('$thread_ret_type ${wrapper_fn_name}($wrapper_struct_name *arg);')
|
||||
g.gowrappers.writeln('$thread_ret_type ${wrapper_fn_name}($wrapper_struct_name *arg) {')
|
||||
if node.call_expr.return_type != ast.void_type {
|
||||
if g.pref.os == .windows {
|
||||
g.gowrappers.write_string('\t*(($s_ret_typ*)(arg->ret_ptr)) = ')
|
||||
need_return_ptr := g.pref.os == .windows && node.call_expr.return_type != ast.void_type
|
||||
if expr.args.len == 0 && !need_return_ptr {
|
||||
g.type_definitions.writeln('EMPTY_STRUCT_DECLARATION;')
|
||||
} else {
|
||||
g.gowrappers.writeln('\t$s_ret_typ* ret_ptr = malloc(sizeof($s_ret_typ));')
|
||||
g.gowrappers.write_string('\t*ret_ptr = ')
|
||||
for i, arg in expr.args {
|
||||
styp := g.typ(arg.typ)
|
||||
g.type_definitions.writeln('\t$styp arg${i + 1};')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.gowrappers.write_string('\t')
|
||||
}
|
||||
g.gowrappers.write_string('${name}(')
|
||||
if expr.is_method {
|
||||
g.gowrappers.write_string('arg->arg0')
|
||||
if expr.args.len > 0 {
|
||||
g.gowrappers.write_string(', ')
|
||||
if need_return_ptr {
|
||||
g.type_definitions.writeln('\tvoid* ret_ptr;')
|
||||
}
|
||||
}
|
||||
for i in 0 .. expr.args.len {
|
||||
g.gowrappers.write_string('arg->arg${i + 1}')
|
||||
if i < expr.args.len - 1 {
|
||||
g.gowrappers.write_string(', ')
|
||||
g.type_definitions.writeln('} $wrapper_struct_name;')
|
||||
thread_ret_type := if g.pref.os == .windows { 'u32' } else { 'void*' }
|
||||
g.type_definitions.writeln('$thread_ret_type ${wrapper_fn_name}($wrapper_struct_name *arg);')
|
||||
g.gowrappers.writeln('$thread_ret_type ${wrapper_fn_name}($wrapper_struct_name *arg) {')
|
||||
if node.call_expr.return_type != ast.void_type {
|
||||
if g.pref.os == .windows {
|
||||
g.gowrappers.write_string('\t*(($s_ret_typ*)(arg->ret_ptr)) = ')
|
||||
} else {
|
||||
g.gowrappers.writeln('\t$s_ret_typ* ret_ptr = malloc(sizeof($s_ret_typ));')
|
||||
g.gowrappers.write_string('\t*ret_ptr = ')
|
||||
}
|
||||
} else {
|
||||
g.gowrappers.write_string('\t')
|
||||
}
|
||||
g.gowrappers.write_string('${name}(')
|
||||
if expr.is_method {
|
||||
g.gowrappers.write_string('arg->arg0')
|
||||
if expr.args.len > 0 {
|
||||
g.gowrappers.write_string(', ')
|
||||
}
|
||||
}
|
||||
for i in 0 .. expr.args.len {
|
||||
g.gowrappers.write_string('arg->arg${i + 1}')
|
||||
if i < expr.args.len - 1 {
|
||||
g.gowrappers.write_string(', ')
|
||||
}
|
||||
}
|
||||
g.gowrappers.writeln(');')
|
||||
g.gowrappers.writeln('\tfree(arg);')
|
||||
if g.pref.os != .windows && node.call_expr.return_type != ast.void_type {
|
||||
g.gowrappers.writeln('\treturn ret_ptr;')
|
||||
} else {
|
||||
g.gowrappers.writeln('\treturn 0;')
|
||||
}
|
||||
g.gowrappers.writeln('}')
|
||||
g.threaded_fns << name
|
||||
}
|
||||
g.gowrappers.writeln(');')
|
||||
g.gowrappers.writeln('\tfree(arg);')
|
||||
if g.pref.os != .windows && node.call_expr.return_type != ast.void_type {
|
||||
g.gowrappers.writeln('\treturn ret_ptr;')
|
||||
} else {
|
||||
g.gowrappers.writeln('\treturn 0;')
|
||||
if node.is_expr {
|
||||
g.empty_line = false
|
||||
g.write(line)
|
||||
g.write(handle)
|
||||
}
|
||||
g.gowrappers.writeln('}')
|
||||
g.threaded_fns << name
|
||||
return handle
|
||||
}
|
||||
|
||||
fn (mut g Gen) as_cast(node ast.AsCast) {
|
||||
|
@ -405,10 +405,6 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||
ast.GlobalDecl {
|
||||
// TODO
|
||||
}
|
||||
ast.GoStmt {
|
||||
g.gen_go_stmt(node)
|
||||
g.writeln('')
|
||||
}
|
||||
ast.GotoLabel {
|
||||
g.writeln('${g.js_name(node.name)}:')
|
||||
}
|
||||
@ -499,7 +495,7 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
||||
g.gen_float_literal_expr(node)
|
||||
}
|
||||
ast.GoExpr {
|
||||
// TODO
|
||||
g.gen_go_expr(node)
|
||||
}
|
||||
ast.Ident {
|
||||
g.gen_ident(node)
|
||||
@ -800,11 +796,14 @@ fn (mut g JsGen) gen_fn_decl(it ast.FnDecl) {
|
||||
g.gen_method_decl(it)
|
||||
}
|
||||
|
||||
fn fn_has_go(it ast.FnDecl) bool {
|
||||
fn fn_has_go(node ast.FnDecl) bool {
|
||||
mut has_go := false
|
||||
for stmt in it.stmts {
|
||||
if stmt is ast.GoStmt {
|
||||
has_go = true
|
||||
for stmt in node.stmts {
|
||||
if stmt is ast.ExprStmt {
|
||||
if stmt.expr is ast.GoExpr {
|
||||
has_go = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return has_go
|
||||
@ -989,8 +988,9 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) {
|
||||
g.writeln('}')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_go_stmt(node ast.GoStmt) {
|
||||
// x := node.call_expr as ast.CallEpxr // TODO
|
||||
fn (mut g JsGen) gen_go_expr(node ast.GoExpr) {
|
||||
// TODO Handle joinable expressions
|
||||
// node.is_expr
|
||||
mut name := node.call_expr.name
|
||||
if node.call_expr.is_method {
|
||||
receiver_sym := g.table.get_type_symbol(node.call_expr.receiver_type)
|
||||
|
@ -90,9 +90,6 @@ pub fn (mut w Walker) stmt(node ast.Stmt) {
|
||||
w.expr(node.cond)
|
||||
w.stmts(node.stmts)
|
||||
}
|
||||
ast.GoStmt {
|
||||
w.expr(node.call_expr)
|
||||
}
|
||||
ast.Return {
|
||||
w.exprs(node.exprs)
|
||||
}
|
||||
@ -201,7 +198,7 @@ fn (mut w Walker) expr(node ast.Expr) {
|
||||
w.fn_by_name('eprintln')
|
||||
}
|
||||
ast.GoExpr {
|
||||
w.expr(node.go_stmt.call_expr)
|
||||
w.expr(node.call_expr)
|
||||
}
|
||||
ast.IndexExpr {
|
||||
w.expr(node.left)
|
||||
|
@ -801,20 +801,10 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||
}
|
||||
}
|
||||
.key_go {
|
||||
p.next()
|
||||
spos := p.tok.position()
|
||||
expr := p.expr(0)
|
||||
call_expr := if expr is ast.CallExpr {
|
||||
expr
|
||||
} else {
|
||||
p.error_with_pos('expression in `go` must be a function call', expr.position())
|
||||
ast.CallExpr{
|
||||
scope: p.scope
|
||||
}
|
||||
}
|
||||
return ast.GoStmt{
|
||||
call_expr: call_expr
|
||||
pos: spos.extend(p.prev_tok.position())
|
||||
go_expr := p.go_expr()
|
||||
return ast.ExprStmt{
|
||||
expr: go_expr
|
||||
pos: go_expr.pos
|
||||
}
|
||||
}
|
||||
.key_goto {
|
||||
|
@ -92,12 +92,9 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||
}
|
||||
}
|
||||
.key_go {
|
||||
stmt := p.stmt(false)
|
||||
go_stmt := stmt as ast.GoStmt
|
||||
node = ast.GoExpr{
|
||||
go_stmt: go_stmt
|
||||
pos: go_stmt.pos
|
||||
}
|
||||
mut go_expr := p.go_expr()
|
||||
go_expr.is_expr = true
|
||||
node = go_expr
|
||||
}
|
||||
.key_true, .key_false {
|
||||
node = ast.BoolLiteral{
|
||||
@ -490,6 +487,25 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) go_expr() ast.GoExpr {
|
||||
p.next()
|
||||
spos := p.tok.position()
|
||||
expr := p.expr(0)
|
||||
call_expr := if expr is ast.CallExpr {
|
||||
expr
|
||||
} else {
|
||||
p.error_with_pos('expression in `go` must be a function call', expr.position())
|
||||
ast.CallExpr{
|
||||
scope: p.scope
|
||||
}
|
||||
}
|
||||
pos := spos.extend(p.prev_tok.position())
|
||||
return ast.GoExpr{
|
||||
call_expr: call_expr
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
|
||||
fn (p &Parser) fileis(s string) bool {
|
||||
return p.file_name.contains(s)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user