mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: enable printing for all supported expressions (#16270)
This commit is contained in:
parent
339bd0c4b5
commit
1b721250e0
@ -1225,9 +1225,8 @@ 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, fd int) {
|
||||
mystrlen := true // if n < 0 maybe?
|
||||
g.mov_reg(.rsi, r)
|
||||
if mystrlen {
|
||||
if n < 0 {
|
||||
g.inline_strlen(.rsi)
|
||||
g.mov_reg(.rdx, .rax)
|
||||
} else {
|
||||
@ -2621,14 +2620,6 @@ fn (mut g Gen) trap() {
|
||||
g.println('trap')
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_asm_stmt(asm_node ast.AsmStmt) {
|
||||
if g.pref.arch == .arm64 {
|
||||
g.gen_asm_stmt_arm64(asm_node)
|
||||
} else {
|
||||
g.gen_asm_stmt_amd64(asm_node)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
|
||||
// inline assembly using vasm
|
||||
g.println('// asm inline')
|
||||
|
@ -660,11 +660,11 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
||||
// skip \
|
||||
i++
|
||||
match str[i] {
|
||||
`\\` {
|
||||
buffer << `\\`
|
||||
`\\`, `'`, `"` {
|
||||
buffer << str[i]
|
||||
i++
|
||||
}
|
||||
`a` | `b` | `f` {
|
||||
`a`, `b`, `f` {
|
||||
buffer << str[i] - u8(90)
|
||||
i++
|
||||
}
|
||||
@ -720,6 +720,33 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
||||
return buffer.bytestr()
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_to_string(reg Register, typ ast.Type) {
|
||||
if typ.is_int() {
|
||||
buffer := g.allocate_array('itoa-buffer', 1, 32) // 32 characters should be enough
|
||||
g.lea_var_to_reg(g.get_builtin_arg_reg('int_to_string', 1), buffer)
|
||||
|
||||
arg0_reg := g.get_builtin_arg_reg('int_to_string', 0)
|
||||
if arg0_reg != reg {
|
||||
g.mov_reg(arg0_reg, reg)
|
||||
}
|
||||
|
||||
g.call_builtin('int_to_string')
|
||||
g.lea_var_to_reg(.rax, buffer)
|
||||
} else if typ.is_bool() {
|
||||
arg_reg := g.get_builtin_arg_reg('bool_to_string', 0)
|
||||
if arg_reg != reg {
|
||||
g.mov_reg(arg_reg, reg)
|
||||
}
|
||||
g.call_builtin('bool_to_string')
|
||||
} else if typ.is_string() {
|
||||
if reg != .rax {
|
||||
g.mov_reg(.rax, reg)
|
||||
}
|
||||
} else {
|
||||
g.n_error('int-to-string conversion not implemented for type $typ')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
||||
typ := g.get_type_from_var(var)
|
||||
if typ.is_int() {
|
||||
@ -738,7 +765,7 @@ fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
|
||||
pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
|
||||
newline := name in ['println', 'eprintln']
|
||||
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
|
||||
match expr {
|
||||
@ -750,70 +777,66 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
|
||||
g.gen_print(str, fd)
|
||||
}
|
||||
}
|
||||
ast.CallExpr {
|
||||
g.call_fn(expr)
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
}
|
||||
ast.Ident {
|
||||
vo := g.try_var_offset(expr.name)
|
||||
|
||||
if vo != -1 {
|
||||
g.gen_var_to_string(.rax, expr as ast.Ident)
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
g.gen_print_reg(.rax, -1, fd)
|
||||
if newline {
|
||||
g.gen_print('\n', fd)
|
||||
}
|
||||
} else {
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
g.gen_print_reg(.rax, -1, fd)
|
||||
}
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
g.learel(.rax, g.allocate_string('$expr.val\n', 3, .rel32))
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
if newline {
|
||||
g.gen_print('$expr.val\n', fd)
|
||||
} else {
|
||||
g.gen_print('$expr.val', fd)
|
||||
}
|
||||
}
|
||||
ast.BoolLiteral {
|
||||
// register 'true' and 'false' strings // g.expr(expr)
|
||||
// XXX mov64 shuoldnt be used for addressing
|
||||
nl := if newline { '\n' } else { '' }
|
||||
|
||||
if expr.val {
|
||||
g.learel(.rax, g.allocate_string('true', 3, .rel32))
|
||||
g.gen_print('true' + nl, fd)
|
||||
} else {
|
||||
g.learel(.rax, g.allocate_string('false', 3, .rel32))
|
||||
g.gen_print('false' + nl, fd)
|
||||
}
|
||||
}
|
||||
ast.SizeOf {
|
||||
size := g.get_type_size(expr.typ)
|
||||
if newline {
|
||||
g.gen_print('$size\n', fd)
|
||||
} else {
|
||||
g.gen_print('$size', fd)
|
||||
}
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
}
|
||||
ast.SizeOf {}
|
||||
ast.OffsetOf {
|
||||
styp := g.typ(expr.struct_type)
|
||||
field_name := expr.field
|
||||
if styp.kind == .struct_ {
|
||||
off := g.get_field_offset(expr.struct_type, field_name)
|
||||
g.learel(.rax, g.allocate_string('$off\n', 3, .rel32))
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
if newline {
|
||||
g.gen_print('$off\n', fd)
|
||||
} else {
|
||||
g.gen_print('$off', fd)
|
||||
}
|
||||
} else {
|
||||
g.v_error('_offsetof expects a struct Type as first argument', expr.pos)
|
||||
}
|
||||
}
|
||||
ast.None {}
|
||||
ast.EmptyExpr {
|
||||
g.n_error('unhandled EmptyExpr')
|
||||
ast.None {
|
||||
if newline {
|
||||
g.gen_print('<none>\n', fd)
|
||||
} else {
|
||||
g.gen_print('<none>', fd)
|
||||
}
|
||||
ast.PostfixExpr {}
|
||||
ast.PrefixExpr {}
|
||||
ast.SelectorExpr {
|
||||
// struct.field
|
||||
g.expr(expr)
|
||||
g.gen_print_reg(.rax, 3, fd)
|
||||
/*
|
||||
field_name := expr.field_name
|
||||
g.expr
|
||||
if expr.is_mut {
|
||||
// mutable field access (rw)
|
||||
}
|
||||
*/
|
||||
dump(expr)
|
||||
g.v_error('struct.field selector not yet implemented for this backend', expr.pos)
|
||||
}
|
||||
ast.NodeError {}
|
||||
ast.AtExpr {
|
||||
if newline {
|
||||
g.gen_print(g.comptime_at(expr) + '\n', fd)
|
||||
@ -821,54 +844,6 @@ g.expr
|
||||
g.gen_print(g.comptime_at(expr), fd)
|
||||
}
|
||||
}
|
||||
/*
|
||||
ast.AnonFn {}
|
||||
ast.ArrayDecompose {}
|
||||
ast.ArrayInit {}
|
||||
ast.AsCast {}
|
||||
ast.Assoc {}
|
||||
ast.CTempVar {}
|
||||
ast.CastExpr {}
|
||||
ast.ChanInit {}
|
||||
ast.CharLiteral {}
|
||||
ast.Comment {}
|
||||
ast.ComptimeCall {}
|
||||
ast.ComptimeSelector {}
|
||||
ast.ConcatExpr {}
|
||||
ast.DumpExpr {}
|
||||
ast.EnumVal {}
|
||||
ast.GoExpr {}
|
||||
ast.IfGuardExpr {}
|
||||
ast.IndexExpr {}
|
||||
ast.InfixExpr {}
|
||||
ast.IsRefType {}
|
||||
ast.MapInit {}
|
||||
ast.OrExpr {}
|
||||
ast.ParExpr {}
|
||||
ast.RangeExpr {}
|
||||
ast.SelectExpr {}
|
||||
ast.SqlExpr {}
|
||||
ast.TypeNode {}
|
||||
*/
|
||||
ast.MatchExpr {
|
||||
g.gen_match_expr(expr)
|
||||
}
|
||||
ast.TypeOf {
|
||||
g.gen_typeof_expr(expr, newline)
|
||||
}
|
||||
ast.LockExpr {
|
||||
// passthru
|
||||
eprintln('Warning: locks not implemented yet in the native backend')
|
||||
g.expr(expr)
|
||||
}
|
||||
ast.Likely {
|
||||
// passthru
|
||||
g.expr(expr)
|
||||
}
|
||||
ast.UnsafeExpr {
|
||||
// passthru
|
||||
g.expr(expr)
|
||||
}
|
||||
ast.StringInterLiteral {
|
||||
g.n_error('Interlaced string literals are not yet supported in the native backend.') // , expr.pos)
|
||||
}
|
||||
@ -877,7 +852,7 @@ g.expr
|
||||
if stmts := g.comptime_conditional(expr) {
|
||||
for i, stmt in stmts {
|
||||
if i + 1 == stmts.len && stmt is ast.ExprStmt {
|
||||
g.gen_print_from_expr(stmt.expr, name)
|
||||
g.gen_print_from_expr(stmt.expr, stmt.typ, name)
|
||||
} else {
|
||||
g.stmt(stmt)
|
||||
}
|
||||
@ -886,14 +861,16 @@ g.expr
|
||||
g.n_error('nothing to print')
|
||||
}
|
||||
} else {
|
||||
g.n_error('non-comptime if exprs not yet implemented')
|
||||
g.n_error('non-comptime conditionals are not implemented yet.')
|
||||
}
|
||||
}
|
||||
else {
|
||||
dump(typeof(expr).name)
|
||||
dump(expr)
|
||||
// g.v_error('expected string as argument for print', expr.pos)
|
||||
g.n_error('expected string as argument for print') // , expr.pos)
|
||||
g.expr(expr)
|
||||
g.gen_to_string(.rax, typ)
|
||||
g.gen_print_reg(.rax, -1, fd)
|
||||
if newline {
|
||||
g.gen_print('\n', fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1244,6 +1221,14 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_asm_stmt(asm_node ast.AsmStmt) {
|
||||
if g.pref.arch == .arm64 {
|
||||
g.gen_asm_stmt_arm64(asm_node)
|
||||
} else {
|
||||
g.gen_asm_stmt_amd64(asm_node)
|
||||
}
|
||||
}
|
||||
|
||||
fn C.strtol(str &char, endptr &&char, base int) int
|
||||
|
||||
fn (mut g Gen) gen_syscall(node ast.CallExpr) {
|
||||
@ -1321,7 +1306,8 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.gen_exit(node.args[0].expr)
|
||||
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
||||
expr := node.args[0].expr
|
||||
g.gen_print_from_expr(expr, node.name)
|
||||
typ := node.args[0].typ
|
||||
g.gen_print_from_expr(expr, typ, node.name)
|
||||
} else {
|
||||
g.call_fn(node)
|
||||
}
|
||||
|
@ -70,10 +70,36 @@ fn test_idents() {
|
||||
println(r'hello\tworld\n')
|
||||
}
|
||||
|
||||
fn test_exprs() {
|
||||
t := true
|
||||
print(t == false)
|
||||
print(' ')
|
||||
println(t == true)
|
||||
|
||||
i := 123
|
||||
println(i + 456)
|
||||
|
||||
j := 2
|
||||
println(j + j * j)
|
||||
|
||||
println(none)
|
||||
}
|
||||
|
||||
fn test_sizeof() {
|
||||
i := 0
|
||||
|
||||
print('sizeof: ')
|
||||
print(sizeof(i))
|
||||
print(', ')
|
||||
println(sizeof(Foo))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_stdout()
|
||||
test_stderr()
|
||||
test_numbers()
|
||||
test_oof()
|
||||
test_idents()
|
||||
test_exprs()
|
||||
test_sizeof()
|
||||
}
|
||||
|
@ -14,3 +14,8 @@ string blah blah blah
|
||||
😀😆😎💻🌎
|
||||
こんにちは
|
||||
hello\tworld\n
|
||||
false true
|
||||
579
|
||||
6
|
||||
<none>
|
||||
sizeof: 4, 12
|
||||
|
Loading…
Reference in New Issue
Block a user