native: add support for print, eprint and eprintln (#11034)

pull/11039/head
pancake 2021-08-03 15:04:31 +02:00 committed by GitHub
parent 80976e640c
commit 00d4c7082e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 50 additions and 13 deletions

View File

@ -346,7 +346,7 @@ pub fn execute(cmd string) Result {
// if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') {
// 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)
if isnil(f) {
return Result{

View File

@ -457,7 +457,7 @@ pub fn (mut g Gen) inline_strlen(r Register) {
}
// 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
g.mov_reg(.rsi, r)
if mystrlen {
@ -467,16 +467,16 @@ pub fn (mut g Gen) gen_print_reg(r Register, n int) {
g.mov(.edx, n)
}
g.mov(.eax, g.nsyscall_write())
g.mov(.edi, 1)
g.mov(.edi, fd)
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'
//
g.mov(.eax, g.nsyscall_write())
g.mov(.edi, 1)
g.mov(.edi, fd)
// segment_start + 0x9f) // str pos // placeholder
g.mov64(.rsi, g.allocate_string(s, 2)) // for rsi its 2
g.mov(.edx, s.len) // len

View File

@ -12,7 +12,7 @@ import v.errors
import v.pref
import term
pub const builtins = ['println', 'exit']
pub const builtins = ['print', 'eprint', 'println', 'eprintln', 'exit']
interface CodeGen {
mut:
@ -227,22 +227,24 @@ fn (mut g Gen) get_var_offset(var_name string) int {
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 {
ast.StringLiteral {
if newline {
g.gen_print(expr.val + '\n')
g.gen_print(expr.val + '\n', fd)
} else {
g.gen_print(expr.val)
g.gen_print(expr.val, fd)
}
}
ast.CallExpr {
g.call_fn(expr)
g.gen_print_reg(.rax, 3)
g.gen_print_reg(.rax, 3, fd)
}
ast.Ident {
g.expr(expr)
g.gen_print_reg(.rax, 3)
g.gen_print_reg(.rax, 3, fd)
}
else {
dump(typeof(expr).name)
@ -389,7 +391,7 @@ fn (mut g Gen) expr(node ast.Expr) {
}
if node.name in ['println', 'print', 'eprintln', 'eprint'] {
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
}
g.call_fn(node)

View File

@ -46,7 +46,8 @@ fn test_native() {
eprintln(bench.step_message_fail(cmd))
continue
}
res := os.execute(exe_test_path)
tmperrfile := '$dir/${test}.tmperr'
res := os.execute('$exe_test_path 2> $tmperrfile')
if res.exit_code != 0 {
bench.fail()
eprintln(bench.step_message_fail('$full_test_path failed to run'))
@ -54,6 +55,24 @@ fn test_native() {
continue
}
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')
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
found = found.trim_space()

View File

@ -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()
}

View File

@ -0,0 +1 @@
2(Hello)2(World)

View File

@ -0,0 +1 @@
Hello World