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