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
|
// TODO: strlen of string at runtime
|
||||||
pub fn (mut g Gen) gen_print_reg(r Register, n int, fd int) {
|
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)
|
g.mov_reg(.rsi, r)
|
||||||
if mystrlen {
|
if n < 0 {
|
||||||
g.inline_strlen(.rsi)
|
g.inline_strlen(.rsi)
|
||||||
g.mov_reg(.rdx, .rax)
|
g.mov_reg(.rdx, .rax)
|
||||||
} else {
|
} else {
|
||||||
@ -2621,14 +2620,6 @@ fn (mut g Gen) trap() {
|
|||||||
g.println('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) {
|
fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
|
||||||
// inline assembly using vasm
|
// inline assembly using vasm
|
||||||
g.println('// asm inline')
|
g.println('// asm inline')
|
||||||
|
@ -660,11 +660,11 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
|||||||
// skip \
|
// skip \
|
||||||
i++
|
i++
|
||||||
match str[i] {
|
match str[i] {
|
||||||
`\\` {
|
`\\`, `'`, `"` {
|
||||||
buffer << `\\`
|
buffer << str[i]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
`a` | `b` | `f` {
|
`a`, `b`, `f` {
|
||||||
buffer << str[i] - u8(90)
|
buffer << str[i] - u8(90)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -720,6 +720,33 @@ fn (mut g Gen) eval_escape_codes(str_lit ast.StringLiteral) string {
|
|||||||
return buffer.bytestr()
|
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) {
|
fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
||||||
typ := g.get_type_from_var(var)
|
typ := g.get_type_from_var(var)
|
||||||
if typ.is_int() {
|
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']
|
newline := name in ['println', 'eprintln']
|
||||||
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
|
fd := if name in ['eprint', 'eprintln'] { 2 } else { 1 }
|
||||||
match expr {
|
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)
|
g.gen_print(str, fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
|
||||||
g.call_fn(expr)
|
|
||||||
g.gen_print_reg(.rax, 3, fd)
|
|
||||||
}
|
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
vo := g.try_var_offset(expr.name)
|
vo := g.try_var_offset(expr.name)
|
||||||
|
|
||||||
if vo != -1 {
|
if vo != -1 {
|
||||||
g.gen_var_to_string(.rax, expr as ast.Ident)
|
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 {
|
if newline {
|
||||||
g.gen_print('\n', fd)
|
g.gen_print('\n', fd)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.gen_print_reg(.rax, 3, fd)
|
g.gen_print_reg(.rax, -1, fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
g.learel(.rax, g.allocate_string('$expr.val\n', 3, .rel32))
|
if newline {
|
||||||
g.gen_print_reg(.rax, 3, fd)
|
g.gen_print('$expr.val\n', fd)
|
||||||
|
} else {
|
||||||
|
g.gen_print('$expr.val', fd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.BoolLiteral {
|
ast.BoolLiteral {
|
||||||
// register 'true' and 'false' strings // g.expr(expr)
|
// register 'true' and 'false' strings // g.expr(expr)
|
||||||
// XXX mov64 shuoldnt be used for addressing
|
// XXX mov64 shuoldnt be used for addressing
|
||||||
|
nl := if newline { '\n' } else { '' }
|
||||||
|
|
||||||
if expr.val {
|
if expr.val {
|
||||||
g.learel(.rax, g.allocate_string('true', 3, .rel32))
|
g.gen_print('true' + nl, fd)
|
||||||
} else {
|
} 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 {
|
ast.OffsetOf {
|
||||||
styp := g.typ(expr.struct_type)
|
styp := g.typ(expr.struct_type)
|
||||||
field_name := expr.field
|
field_name := expr.field
|
||||||
if styp.kind == .struct_ {
|
if styp.kind == .struct_ {
|
||||||
off := g.get_field_offset(expr.struct_type, field_name)
|
off := g.get_field_offset(expr.struct_type, field_name)
|
||||||
g.learel(.rax, g.allocate_string('$off\n', 3, .rel32))
|
if newline {
|
||||||
g.gen_print_reg(.rax, 3, fd)
|
g.gen_print('$off\n', fd)
|
||||||
|
} else {
|
||||||
|
g.gen_print('$off', fd)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.v_error('_offsetof expects a struct Type as first argument', expr.pos)
|
g.v_error('_offsetof expects a struct Type as first argument', expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.None {}
|
ast.None {
|
||||||
ast.EmptyExpr {
|
if newline {
|
||||||
g.n_error('unhandled EmptyExpr')
|
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 {
|
ast.AtExpr {
|
||||||
if newline {
|
if newline {
|
||||||
g.gen_print(g.comptime_at(expr) + '\n', fd)
|
g.gen_print(g.comptime_at(expr) + '\n', fd)
|
||||||
@ -821,54 +844,6 @@ g.expr
|
|||||||
g.gen_print(g.comptime_at(expr), fd)
|
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 {
|
ast.StringInterLiteral {
|
||||||
g.n_error('Interlaced string literals are not yet supported in the native backend.') // , expr.pos)
|
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) {
|
if stmts := g.comptime_conditional(expr) {
|
||||||
for i, stmt in stmts {
|
for i, stmt in stmts {
|
||||||
if i + 1 == stmts.len && stmt is ast.ExprStmt {
|
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 {
|
} else {
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
}
|
}
|
||||||
@ -886,14 +861,16 @@ g.expr
|
|||||||
g.n_error('nothing to print')
|
g.n_error('nothing to print')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.n_error('non-comptime if exprs not yet implemented')
|
g.n_error('non-comptime conditionals are not implemented yet.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dump(typeof(expr).name)
|
g.expr(expr)
|
||||||
dump(expr)
|
g.gen_to_string(.rax, typ)
|
||||||
// g.v_error('expected string as argument for print', expr.pos)
|
g.gen_print_reg(.rax, -1, fd)
|
||||||
g.n_error('expected string as argument for print') // , expr.pos)
|
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 C.strtol(str &char, endptr &&char, base int) int
|
||||||
|
|
||||||
fn (mut g Gen) gen_syscall(node ast.CallExpr) {
|
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)
|
g.gen_exit(node.args[0].expr)
|
||||||
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
} else 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)
|
typ := node.args[0].typ
|
||||||
|
g.gen_print_from_expr(expr, typ, node.name)
|
||||||
} else {
|
} else {
|
||||||
g.call_fn(node)
|
g.call_fn(node)
|
||||||
}
|
}
|
||||||
|
@ -70,10 +70,36 @@ fn test_idents() {
|
|||||||
println(r'hello\tworld\n')
|
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() {
|
fn main() {
|
||||||
test_stdout()
|
test_stdout()
|
||||||
test_stderr()
|
test_stderr()
|
||||||
test_numbers()
|
test_numbers()
|
||||||
test_oof()
|
test_oof()
|
||||||
test_idents()
|
test_idents()
|
||||||
|
test_exprs()
|
||||||
|
test_sizeof()
|
||||||
}
|
}
|
||||||
|
@ -14,3 +14,8 @@ string blah blah blah
|
|||||||
😀😆😎💻🌎
|
😀😆😎💻🌎
|
||||||
こんにちは
|
こんにちは
|
||||||
hello\tworld\n
|
hello\tworld\n
|
||||||
|
false true
|
||||||
|
579
|
||||||
|
6
|
||||||
|
<none>
|
||||||
|
sizeof: 4, 12
|
||||||
|
Loading…
x
Reference in New Issue
Block a user