native: add support for print, eprint and eprintln (#11034)
parent
80976e640c
commit
00d4c7082e
|
@ -346,7 +346,7 @@ pub fn execute(cmd string) Result {
|
||||||
// if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
// if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
|
||||||
// return Result{ exit_code: -1, output: ';, &&, || and \\n are not allowed in shell commands' }
|
// return Result{ exit_code: -1, output: ';, &&, || and \\n are not allowed in shell commands' }
|
||||||
// }
|
// }
|
||||||
pcmd := '$cmd 2>&1'
|
pcmd := if cmd.contains('2>') { cmd } else { '$cmd 2>&1' }
|
||||||
f := vpopen(pcmd)
|
f := vpopen(pcmd)
|
||||||
if isnil(f) {
|
if isnil(f) {
|
||||||
return Result{
|
return Result{
|
||||||
|
|
|
@ -457,7 +457,7 @@ pub fn (mut g Gen) inline_strlen(r Register) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: strlen of string at runtime
|
// TODO: strlen of string at runtime
|
||||||
pub fn (mut g Gen) gen_print_reg(r Register, n int) {
|
pub fn (mut g Gen) gen_print_reg(r Register, n int, fd int) {
|
||||||
mystrlen := true
|
mystrlen := true
|
||||||
g.mov_reg(.rsi, r)
|
g.mov_reg(.rsi, r)
|
||||||
if mystrlen {
|
if mystrlen {
|
||||||
|
@ -467,16 +467,16 @@ pub fn (mut g Gen) gen_print_reg(r Register, n int) {
|
||||||
g.mov(.edx, n)
|
g.mov(.edx, n)
|
||||||
}
|
}
|
||||||
g.mov(.eax, g.nsyscall_write())
|
g.mov(.eax, g.nsyscall_write())
|
||||||
g.mov(.edi, 1)
|
g.mov(.edi, fd)
|
||||||
g.syscall()
|
g.syscall()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) gen_print(s string) {
|
pub fn (mut g Gen) gen_print(s string, fd int) {
|
||||||
//
|
//
|
||||||
// qq := s + '\n'
|
// qq := s + '\n'
|
||||||
//
|
//
|
||||||
g.mov(.eax, g.nsyscall_write())
|
g.mov(.eax, g.nsyscall_write())
|
||||||
g.mov(.edi, 1)
|
g.mov(.edi, fd)
|
||||||
// segment_start + 0x9f) // str pos // placeholder
|
// segment_start + 0x9f) // str pos // placeholder
|
||||||
g.mov64(.rsi, g.allocate_string(s, 2)) // for rsi its 2
|
g.mov64(.rsi, g.allocate_string(s, 2)) // for rsi its 2
|
||||||
g.mov(.edx, s.len) // len
|
g.mov(.edx, s.len) // len
|
||||||
|
|
|
@ -12,7 +12,7 @@ import v.errors
|
||||||
import v.pref
|
import v.pref
|
||||||
import term
|
import term
|
||||||
|
|
||||||
pub const builtins = ['println', 'exit']
|
pub const builtins = ['print', 'eprint', 'println', 'eprintln', 'exit']
|
||||||
|
|
||||||
interface CodeGen {
|
interface CodeGen {
|
||||||
mut:
|
mut:
|
||||||
|
@ -227,22 +227,24 @@ fn (mut g Gen) get_var_offset(var_name string) int {
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, newline bool) {
|
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
|
||||||
|
newline := name in ['println', 'eprintln']
|
||||||
|
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
|
||||||
match expr {
|
match expr {
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
if newline {
|
if newline {
|
||||||
g.gen_print(expr.val + '\n')
|
g.gen_print(expr.val + '\n', fd)
|
||||||
} else {
|
} else {
|
||||||
g.gen_print(expr.val)
|
g.gen_print(expr.val, fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
g.call_fn(expr)
|
g.call_fn(expr)
|
||||||
g.gen_print_reg(.rax, 3)
|
g.gen_print_reg(.rax, 3, fd)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.gen_print_reg(.rax, 3)
|
g.gen_print_reg(.rax, 3, fd)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dump(typeof(expr).name)
|
dump(typeof(expr).name)
|
||||||
|
@ -389,7 +391,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
||||||
expr := node.args[0].expr
|
expr := node.args[0].expr
|
||||||
g.gen_print_from_expr(expr, node.name in ['println', 'eprintln'])
|
g.gen_print_from_expr(expr, node.name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.call_fn(node)
|
g.call_fn(node)
|
||||||
|
|
|
@ -46,7 +46,8 @@ fn test_native() {
|
||||||
eprintln(bench.step_message_fail(cmd))
|
eprintln(bench.step_message_fail(cmd))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
res := os.execute(exe_test_path)
|
tmperrfile := '$dir/${test}.tmperr'
|
||||||
|
res := os.execute('$exe_test_path 2> $tmperrfile')
|
||||||
if res.exit_code != 0 {
|
if res.exit_code != 0 {
|
||||||
bench.fail()
|
bench.fail()
|
||||||
eprintln(bench.step_message_fail('$full_test_path failed to run'))
|
eprintln(bench.step_message_fail('$full_test_path failed to run'))
|
||||||
|
@ -54,6 +55,24 @@ fn test_native() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut expected := os.read_file('$dir/${test}.out') or { panic(err) }
|
mut expected := os.read_file('$dir/${test}.out') or { panic(err) }
|
||||||
|
errfile := '$dir/${test}.err'
|
||||||
|
if os.exists(errfile) {
|
||||||
|
mut err_expected := os.read_file('$dir/${test}.err') or { panic(err) }
|
||||||
|
err_expected = err_expected.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
|
errstr := os.read_file(tmperrfile) or { panic(err) }
|
||||||
|
mut err_found := errstr.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
|
if err_expected != err_found {
|
||||||
|
println(term.red('FAIL'))
|
||||||
|
println('============')
|
||||||
|
println('stderr expected: "$err_expected" len=$err_expected.len')
|
||||||
|
println('============')
|
||||||
|
println('stderr found:"$err_found" len=$err_found.len')
|
||||||
|
println('============\n')
|
||||||
|
bench.fail()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.rm(tmperrfile) or {}
|
||||||
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
|
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
|
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
found = found.trim_space()
|
found = found.trim_space()
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
fn test_stdout() {
|
||||||
|
print('Hello ')
|
||||||
|
println('World')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_stderr() {
|
||||||
|
eprint('2(Hello)')
|
||||||
|
eprintln('2(World)')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test_stdout()
|
||||||
|
test_stderr()
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
2(Hello)2(World)
|
|
@ -0,0 +1 @@
|
||||||
|
Hello World
|
Loading…
Reference in New Issue