native: support `else`, `break`, `continue` (#14738)
parent
da7a166708
commit
c7a619d16e
|
@ -206,10 +206,13 @@ fn (mut g Gen) cjmp(op JumpOp) int {
|
||||||
return int(pos)
|
return int(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) jmp(addr int) {
|
fn (mut g Gen) jmp(addr int) int {
|
||||||
g.write8(0xe9)
|
g.write8(0xe9)
|
||||||
|
pos := g.pos()
|
||||||
g.write32(addr) // 0xffffff
|
g.write32(addr) // 0xffffff
|
||||||
g.println('jmp')
|
g.println('jmp')
|
||||||
|
// return the position of jump address for placeholder
|
||||||
|
return int(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abs(a i64) i64 {
|
fn abs(a i64) i64 {
|
||||||
|
@ -1149,6 +1152,20 @@ fn (mut g Gen) patch_calls() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) patch_labels() {
|
||||||
|
for label in g.labels.patches {
|
||||||
|
addr := g.labels.addrs[label.id]
|
||||||
|
if addr == 0 {
|
||||||
|
g.n_error('label addr = 0')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Update jmp or cjmp address.
|
||||||
|
// The value is the relative address, difference between current position and the location
|
||||||
|
// after `jxx 00 00 00 00`
|
||||||
|
g.write32_at(label.pos, int(addr - label.pos - 4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) delay_fn_call(name string) {
|
fn (mut g Gen) delay_fn_call(name string) {
|
||||||
pos := g.buf.len
|
pos := g.buf.len
|
||||||
g.callpatches << CallPatch{name, pos}
|
g.callpatches << CallPatch{name, pos}
|
||||||
|
@ -1567,10 +1584,17 @@ fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
|
||||||
} else {
|
} else {
|
||||||
g.n_error('Unsupported expression in assert')
|
g.n_error('Unsupported expression in assert')
|
||||||
}
|
}
|
||||||
|
label := g.labels.new_label()
|
||||||
cjmp_addr = g.condition(ine, true)
|
cjmp_addr = g.condition(ine, true)
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: label
|
||||||
|
pos: cjmp_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to label $label')
|
||||||
g.expr(assert_node.expr)
|
g.expr(assert_node.expr)
|
||||||
g.trap()
|
g.trap()
|
||||||
g.write32_at(cjmp_addr, int(g.pos() - cjmp_addr - 4)) // 4 is for "00 00 00 00"
|
g.labels.addrs[label] = g.pos()
|
||||||
|
g.println('; label $label')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) cjmp_notop(op token.Kind) int {
|
fn (mut g Gen) cjmp_notop(op token.Kind) int {
|
||||||
|
@ -1669,14 +1693,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||||
if node.is_comptime {
|
if node.is_comptime {
|
||||||
g.n_error('ignored comptime')
|
g.n_error('ignored comptime')
|
||||||
}
|
}
|
||||||
if node.has_else {
|
|
||||||
g.n_error('else statements not yet supported')
|
|
||||||
}
|
|
||||||
if node.branches.len == 0 {
|
if node.branches.len == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
mut endif_label := 0
|
||||||
|
has_endif := node.branches.len > 1
|
||||||
|
if has_endif {
|
||||||
|
endif_label = g.labels.new_label()
|
||||||
|
}
|
||||||
for idx in 0 .. node.branches.len {
|
for idx in 0 .. node.branches.len {
|
||||||
branch := node.branches[idx]
|
branch := node.branches[idx]
|
||||||
|
if idx == node.branches.len - 1 && node.has_else {
|
||||||
|
g.stmts(branch.stmts)
|
||||||
|
} else {
|
||||||
if branch.cond is ast.BoolLiteral {
|
if branch.cond is ast.BoolLiteral {
|
||||||
if branch.cond.val {
|
if branch.cond.val {
|
||||||
g.stmts(branch.stmts)
|
g.stmts(branch.stmts)
|
||||||
|
@ -1684,13 +1713,30 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
infix_expr := branch.cond as ast.InfixExpr
|
infix_expr := branch.cond as ast.InfixExpr
|
||||||
|
label := g.labels.new_label()
|
||||||
cjmp_addr := g.condition(infix_expr, false)
|
cjmp_addr := g.condition(infix_expr, false)
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: label
|
||||||
|
pos: cjmp_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to label $label')
|
||||||
g.stmts(branch.stmts)
|
g.stmts(branch.stmts)
|
||||||
// Now that we know where we need to jump if the condition is false, update the `jne` call.
|
if has_endif {
|
||||||
// The value is the relative address, difference between current position and the location
|
jump_addr := g.jmp(0)
|
||||||
// after `jne 00 00 00 00`
|
g.labels.patches << LabelPatch{
|
||||||
|
id: endif_label
|
||||||
|
pos: jump_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to label $endif_label')
|
||||||
|
}
|
||||||
// println('after if g.pos=$g.pos() jneaddr=$cjmp_addr')
|
// println('after if g.pos=$g.pos() jneaddr=$cjmp_addr')
|
||||||
g.write32_at(cjmp_addr, int(g.pos() - cjmp_addr - 4)) // 4 is for "00 00 00 00"
|
g.labels.addrs[label] = g.pos()
|
||||||
|
g.println('; label $label')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if has_endif {
|
||||||
|
g.labels.addrs[endif_label] = g.pos()
|
||||||
|
g.println('; label $endif_label')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1712,14 +1758,29 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
||||||
}
|
}
|
||||||
// infinite loop
|
// infinite loop
|
||||||
start := g.pos()
|
start := g.pos()
|
||||||
|
start_label := g.labels.new_label()
|
||||||
|
g.labels.addrs[start_label] = start
|
||||||
|
g.println('; label $start_label')
|
||||||
|
end_label := g.labels.new_label()
|
||||||
|
g.labels.branches << BranchLabel{
|
||||||
|
name: node.label
|
||||||
|
start: start_label
|
||||||
|
end: end_label
|
||||||
|
}
|
||||||
g.stmts(node.stmts)
|
g.stmts(node.stmts)
|
||||||
|
g.labels.branches.pop()
|
||||||
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
g.println('jmp after infinite for')
|
g.println('jmp after infinite for')
|
||||||
|
g.labels.addrs[end_label] = g.pos()
|
||||||
|
g.println('; label $end_label')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
infix_expr := node.cond as ast.InfixExpr
|
infix_expr := node.cond as ast.InfixExpr
|
||||||
mut jump_addr := 0 // location of `jne *00 00 00 00*`
|
mut jump_addr := 0 // location of `jne *00 00 00 00*`
|
||||||
start := g.pos()
|
start := g.pos()
|
||||||
|
start_label := g.labels.new_label()
|
||||||
|
g.labels.addrs[start_label] = start
|
||||||
|
g.println('; label $start_label')
|
||||||
match infix_expr.left {
|
match infix_expr.left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
match infix_expr.right {
|
match infix_expr.right {
|
||||||
|
@ -1752,12 +1813,25 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
||||||
g.n_error('unhandled infix.left')
|
g.n_error('unhandled infix.left')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end_label := g.labels.new_label()
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: end_label
|
||||||
|
pos: jump_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to label $end_label')
|
||||||
|
g.labels.branches << BranchLabel{
|
||||||
|
name: node.label
|
||||||
|
start: start_label
|
||||||
|
end: end_label
|
||||||
|
}
|
||||||
g.stmts(node.stmts)
|
g.stmts(node.stmts)
|
||||||
|
g.labels.branches.pop()
|
||||||
// Go back to `cmp ...`
|
// Go back to `cmp ...`
|
||||||
// Diff between `jmp 00 00 00 00 X` and `cmp`
|
// Diff between `jmp 00 00 00 00 X` and `cmp`
|
||||||
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
// Update the jump addr to current pos
|
// Update the jump addr to current pos
|
||||||
g.write32_at(jump_addr, int(g.pos() - jump_addr - 4)) // 4 is for "00 00 00 00"
|
g.labels.addrs[end_label] = g.pos()
|
||||||
|
g.println('; label $end_label')
|
||||||
g.println('jmp after for')
|
g.println('jmp after for')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1789,6 +1863,8 @@ fn (mut g Gen) fn_decl_amd64(node ast.FnDecl) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// g.leave()
|
// g.leave()
|
||||||
|
g.labels.addrs[0] = g.pos()
|
||||||
|
g.println('; label 0: return')
|
||||||
g.add8(.rsp, g.stackframe_size)
|
g.add8(.rsp, g.stackframe_size)
|
||||||
g.pop(.rbp)
|
g.pop(.rbp)
|
||||||
g.ret()
|
g.ret()
|
||||||
|
|
|
@ -47,6 +47,7 @@ mut:
|
||||||
nlines int
|
nlines int
|
||||||
callpatches []CallPatch
|
callpatches []CallPatch
|
||||||
strs []String
|
strs []String
|
||||||
|
labels &LabelTable
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RelocType {
|
enum RelocType {
|
||||||
|
@ -68,6 +69,32 @@ struct CallPatch {
|
||||||
pos int
|
pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LabelTable {
|
||||||
|
mut:
|
||||||
|
label_id int
|
||||||
|
return_ids []int = [0] // array is for defer
|
||||||
|
addrs []i64 = [i64(0)] // register address of label here
|
||||||
|
patches []LabelPatch // push placeholders
|
||||||
|
branches []BranchLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LabelPatch {
|
||||||
|
id int
|
||||||
|
pos int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BranchLabel {
|
||||||
|
name string
|
||||||
|
start int
|
||||||
|
end int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut l LabelTable) new_label() int {
|
||||||
|
l.label_id++
|
||||||
|
l.addrs << 0
|
||||||
|
return l.label_id
|
||||||
|
}
|
||||||
|
|
||||||
enum Size {
|
enum Size {
|
||||||
_8
|
_8
|
||||||
_16
|
_16
|
||||||
|
@ -108,6 +135,7 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref
|
||||||
eprintln('No available backend for this configuration. Use `-a arm64` or `-a amd64`.')
|
eprintln('No available backend for this configuration. Use `-a arm64` or `-a amd64`.')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
labels: 0
|
||||||
}
|
}
|
||||||
g.code_gen.g = g
|
g.code_gen.g = g
|
||||||
g.generate_header()
|
g.generate_header()
|
||||||
|
@ -458,11 +486,13 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||||
}
|
}
|
||||||
g.stack_var_pos = 0
|
g.stack_var_pos = 0
|
||||||
g.register_function_address(node.name)
|
g.register_function_address(node.name)
|
||||||
|
g.labels = &LabelTable{}
|
||||||
if g.pref.arch == .arm64 {
|
if g.pref.arch == .arm64 {
|
||||||
g.fn_decl_arm64(node)
|
g.fn_decl_arm64(node)
|
||||||
} else {
|
} else {
|
||||||
g.fn_decl_amd64(node)
|
g.fn_decl_amd64(node)
|
||||||
}
|
}
|
||||||
|
g.patch_labels()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) register_function_address(name string) {
|
pub fn (mut g Gen) register_function_address(name string) {
|
||||||
|
@ -505,6 +535,7 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
|
||||||
g.stmts([node.init])
|
g.stmts([node.init])
|
||||||
}
|
}
|
||||||
start := g.pos()
|
start := g.pos()
|
||||||
|
start_label := g.labels.new_label()
|
||||||
mut jump_addr := i64(0)
|
mut jump_addr := i64(0)
|
||||||
if node.has_cond {
|
if node.has_cond {
|
||||||
cond := node.cond
|
cond := node.cond
|
||||||
|
@ -537,12 +568,27 @@ fn (mut g Gen) gen_forc_stmt(node ast.ForCStmt) {
|
||||||
// dump(node.cond)
|
// dump(node.cond)
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
}
|
}
|
||||||
|
end_label := g.labels.new_label()
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: end_label
|
||||||
|
pos: int(jump_addr)
|
||||||
|
}
|
||||||
|
g.println('; jump to label $end_label')
|
||||||
|
g.labels.branches << BranchLabel{
|
||||||
|
name: node.label
|
||||||
|
start: start_label
|
||||||
|
end: end_label
|
||||||
|
}
|
||||||
g.stmts(node.stmts)
|
g.stmts(node.stmts)
|
||||||
|
g.labels.addrs[start_label] = g.pos()
|
||||||
|
g.println('; label $start_label')
|
||||||
if node.has_inc {
|
if node.has_inc {
|
||||||
g.stmts([node.inc])
|
g.stmts([node.inc])
|
||||||
}
|
}
|
||||||
|
g.labels.branches.pop()
|
||||||
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
g.write32_at(jump_addr, int(g.pos() - jump_addr - 4))
|
g.labels.addrs[end_label] = g.pos()
|
||||||
|
g.println('; jump to label $end_label')
|
||||||
|
|
||||||
// loop back
|
// loop back
|
||||||
}
|
}
|
||||||
|
@ -558,14 +604,30 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.mov_reg_to_var(i, .rax) // i = node.cond // initial value
|
g.mov_reg_to_var(i, .rax) // i = node.cond // initial value
|
||||||
start := g.pos() // label-begin:
|
start := g.pos() // label-begin:
|
||||||
|
start_label := g.labels.new_label()
|
||||||
g.mov_var_to_reg(.rbx, i) // rbx = iterator value
|
g.mov_var_to_reg(.rbx, i) // rbx = iterator value
|
||||||
g.expr(node.high) // final value
|
g.expr(node.high) // final value
|
||||||
g.cmp_reg(.rbx, .rax) // rbx = iterator, rax = max value
|
g.cmp_reg(.rbx, .rax) // rbx = iterator, rax = max value
|
||||||
jump_addr := g.cjmp(.jge) // leave loop if i is beyond end
|
jump_addr := g.cjmp(.jge) // leave loop if i is beyond end
|
||||||
|
end_label := g.labels.new_label()
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: end_label
|
||||||
|
pos: jump_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to label $end_label')
|
||||||
|
g.labels.branches << BranchLabel{
|
||||||
|
name: node.label
|
||||||
|
start: start_label
|
||||||
|
end: end_label
|
||||||
|
}
|
||||||
g.stmts(node.stmts)
|
g.stmts(node.stmts)
|
||||||
|
g.labels.addrs[start_label] = g.pos()
|
||||||
|
g.println('; label $start_label')
|
||||||
g.inc_var(node.val_var)
|
g.inc_var(node.val_var)
|
||||||
|
g.labels.branches.pop()
|
||||||
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
g.jmp(int(0xffffffff - (g.pos() + 5 - start) + 1))
|
||||||
g.write32_at(jump_addr, int(g.pos() - jump_addr - 4))
|
g.labels.addrs[end_label] = g.pos()
|
||||||
|
g.println('; label $end_label')
|
||||||
/*
|
/*
|
||||||
} else if node.kind == .array {
|
} else if node.kind == .array {
|
||||||
} else if node.kind == .array_fixed {
|
} else if node.kind == .array_fixed {
|
||||||
|
@ -593,6 +655,26 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
ast.Block {
|
ast.Block {
|
||||||
g.stmts(node.stmts)
|
g.stmts(node.stmts)
|
||||||
}
|
}
|
||||||
|
ast.BranchStmt {
|
||||||
|
label_name := node.label
|
||||||
|
for i := g.labels.branches.len - 1; i >= 0; i-- {
|
||||||
|
branch := g.labels.branches[i]
|
||||||
|
if label_name == '' || label_name == branch.name {
|
||||||
|
label := if node.kind == .key_break {
|
||||||
|
branch.end
|
||||||
|
} else { // continue
|
||||||
|
branch.start
|
||||||
|
}
|
||||||
|
jump_addr := g.jmp(0)
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: label
|
||||||
|
pos: jump_addr
|
||||||
|
}
|
||||||
|
g.println('; jump to $label: $node.kind')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ast.ConstDecl {}
|
ast.ConstDecl {}
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
g.expr(node.expr)
|
g.expr(node.expr)
|
||||||
|
@ -654,10 +736,15 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.n_error('unknown return type $e0.type_name()')
|
g.n_error('unknown return type $e0.type_name()')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// intel specific
|
|
||||||
g.add8(.rsp, g.stackframe_size)
|
// jump to return label
|
||||||
g.pop(.rbp)
|
label := g.labels.return_ids.last()
|
||||||
g.ret()
|
pos := g.jmp(0)
|
||||||
|
g.labels.patches << LabelPatch{
|
||||||
|
id: label
|
||||||
|
pos: pos
|
||||||
|
}
|
||||||
|
g.println('; jump to label $label')
|
||||||
}
|
}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
g.gen_asm_stmt(node)
|
g.gen_asm_stmt(node)
|
||||||
|
|
|
@ -12,6 +12,7 @@ fn test_macho() {
|
||||||
code_gen: native.Amd64{
|
code_gen: native.Amd64{
|
||||||
g: 0
|
g: 0
|
||||||
}
|
}
|
||||||
|
labels: 0
|
||||||
}
|
}
|
||||||
g.generate_macho_header()
|
g.generate_macho_header()
|
||||||
g.generate_macho_footer()
|
g.generate_macho_footer()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
fn main() {
|
fn simple_for_test() {
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i = 0; i < 3; i++ {
|
for i = 0; i < 3; i++ {
|
||||||
println('loop0')
|
println('loop0')
|
||||||
|
@ -23,4 +23,65 @@ fn main() {
|
||||||
println('loop5')
|
println('loop5')
|
||||||
i--
|
i--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn break_continue_test() {
|
||||||
|
mut i := 0
|
||||||
|
for i = 0; i < 3; i++ {
|
||||||
|
if i == 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println('loop1')
|
||||||
|
}
|
||||||
|
i = 0
|
||||||
|
for i < 3 {
|
||||||
|
if i == 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println('loop2')
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
for j in 0 .. 3 {
|
||||||
|
if j == 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println('loop3')
|
||||||
|
}
|
||||||
|
for i = 0; i < 3; i++ {
|
||||||
|
if i < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println('loop4')
|
||||||
|
}
|
||||||
|
i = 0
|
||||||
|
for i < 3 {
|
||||||
|
if i < 1 {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println('loop5')
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
for j in 0 .. 3 {
|
||||||
|
if j < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println('loop6')
|
||||||
|
}
|
||||||
|
outer: for j in 0 .. 3 {
|
||||||
|
for k in 0 .. 3 {
|
||||||
|
println('loop7')
|
||||||
|
if j == 1 {
|
||||||
|
if k == 1 {
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
simple_for_test()
|
||||||
|
break_continue_test()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,3 +16,20 @@ loop4
|
||||||
loop5
|
loop5
|
||||||
loop5
|
loop5
|
||||||
loop5
|
loop5
|
||||||
|
loop1
|
||||||
|
loop1
|
||||||
|
loop2
|
||||||
|
loop2
|
||||||
|
loop3
|
||||||
|
loop3
|
||||||
|
loop4
|
||||||
|
loop4
|
||||||
|
loop5
|
||||||
|
loop5
|
||||||
|
loop6
|
||||||
|
loop6
|
||||||
|
loop7
|
||||||
|
loop7
|
||||||
|
loop7
|
||||||
|
loop7
|
||||||
|
loop7
|
||||||
|
|
|
@ -40,7 +40,6 @@ fn test_add() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn test_elses() {
|
fn test_elses() {
|
||||||
println('start else')
|
println('start else')
|
||||||
if 1 < 2 {
|
if 1 < 2 {
|
||||||
|
@ -55,11 +54,10 @@ fn test_elses() {
|
||||||
}
|
}
|
||||||
println('end else')
|
println('end else')
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println('start')
|
println('start')
|
||||||
test_add()
|
test_add()
|
||||||
// test_elses()
|
test_elses()
|
||||||
println('end')
|
println('end')
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,8 @@ var(3) > 1
|
||||||
1 < 3
|
1 < 3
|
||||||
1 == 1
|
1 == 1
|
||||||
1 != 3
|
1 != 3
|
||||||
|
start else
|
||||||
|
ok
|
||||||
|
ok
|
||||||
|
end else
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue