From 96cde106960b251f10d179db11a7c8e1e4d7f43e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 15 Nov 2019 02:04:40 +0300 Subject: [PATCH] C string literals (c'str'); bare builtin module; bare println() --- vlib/builtin/bare/builtin_bare.v | 28 ++++++++++++++ vlib/builtin/bare/string_bare.v | 66 ++++++++++++++++++++++++++++++++ vlib/compiler/expression.v | 2 +- vlib/compiler/main.v | 5 ++- vlib/compiler/parser.v | 5 ++- vlib/os/bare/bare.S | 4 +- vlib/os/bare/bare.v | 16 +------- 7 files changed, 106 insertions(+), 20 deletions(-) create mode 100644 vlib/builtin/bare/builtin_bare.v create mode 100644 vlib/builtin/bare/string_bare.v diff --git a/vlib/builtin/bare/builtin_bare.v b/vlib/builtin/bare/builtin_bare.v new file mode 100644 index 0000000000..9019a5fd07 --- /dev/null +++ b/vlib/builtin/bare/builtin_bare.v @@ -0,0 +1,28 @@ +module builtin + +pub fn syscall5(number, arg1, arg2, arg3, arg4, arg5 voidptr) voidptr + +// TODO no pub => error +pub fn write(fd int, data voidptr, nbytes int) int { + return syscall5( + 1, // SYS_write + fd, + data, + nbytes, + 0, // ignored + 0 // ignored + ) +} + +pub fn println(s string) { + write(1, s.str, s.len) +} + +pub fn panic(s string) { + write(1, s.str, s.len) +} + +pub fn malloc(n int) voidptr { + return syscall5(0,0,0,0,0,0) + +} diff --git a/vlib/builtin/bare/string_bare.v b/vlib/builtin/bare/string_bare.v new file mode 100644 index 0000000000..1366c5fce5 --- /dev/null +++ b/vlib/builtin/bare/string_bare.v @@ -0,0 +1,66 @@ +module builtin + +pub struct string { +pub: + str byteptr + len int +} + +pub fn strlen(s byteptr) int { + mut i := 0 + for i = 0; s[i] != 0; i++ { + + } + return i +} + +pub fn tos(s byteptr, len int) string { + if s == 0 { + panic('tos(): nil string') + } + return string { + str: s + len: len + } +} + +pub fn tos_clone(s byteptr) string { + if s == 0 { + panic('tos: nil string') + } + return tos2(s).clone() +} + +// Same as `tos`, but calculates the length. Called by `string(bytes)` casts. +// Used only internally. +pub fn tos2(s byteptr) string { + if s == 0 { + panic('tos2: nil string') + } + return string { + str: s + len: strlen(s) + } +} + +pub fn tos3(s *C.char) string { + if s == 0 { + panic('tos3: nil string') + } + return string { + str: byteptr(s) + len: strlen(byteptr(s)) + } +} + +pub fn (a string) clone() string { + mut b := string { + len: a.len + str: malloc(a.len + 1) + } + for i := 0; i < a.len; i++ { + b[i] = a[i] + } + b[a.len] = `\0` + return b +} diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index 43bbcf93da..ce763858e7 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -161,7 +161,7 @@ fn (p mut Parser) name_expr() string { mut name := p.lit // Raw string (`s := r'hello \n ') - if name == 'r' && p.peek() == .str { + if (name == 'r' || name == 'c') && p.peek() == .str { p.string_expr() return 'string' } diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index 14aed44b2b..2b28256ac7 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -579,7 +579,7 @@ pub fn (v &V) v_files_from_dir(dir string) []string { pub fn (v mut V) add_v_files_to_compile() { mut builtin_files := v.get_builtin_files() if v.pref.is_bare { - builtin_files = [] + //builtin_files = [] } // Builtin cache exists? Use it. builtin_vh := '$v_modules_path${os.path_separator}vlib${os.path_separator}builtin.vh' @@ -651,6 +651,9 @@ pub fn (v mut V) add_v_files_to_compile() { pub fn (v &V) get_builtin_files() []string { // .vh cache exists? Use it + if v.pref.is_bare { + return v.v_files_from_dir(filepath.join(v.vroot, 'vlib', 'builtin', 'bare')) + } $if js { return v.v_files_from_dir('$v.vroot${os.path_separator}vlib${os.path_separator}builtin${os.path_separator}js') } diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index a2fd81320d..546256e7cf 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -2125,7 +2125,8 @@ fn format_str(_str string) string { fn (p mut Parser) string_expr() { is_raw := p.tok == .name && p.lit == 'r' - if is_raw { + is_cstr := p.tok == .name && p.lit == 'c' + if is_raw || is_cstr { p.next() } str := p.lit @@ -2137,7 +2138,7 @@ fn (p mut Parser) string_expr() { Calling a C function sometimes requires a call to a string method C.fun('ssss'.to_wide()) => fun(string_to_wide(tos3("ssss"))) */ - if (p.calling_c && p.peek() != .dot) || p.pref.is_bare || (p.pref.translated && p.mod == 'main') { + if (p.calling_c && p.peek() != .dot) || is_cstr || (p.pref.translated && p.mod == 'main') { p.gen('"$f"') } else if p.is_sql { diff --git a/vlib/os/bare/bare.S b/vlib/os/bare/bare.S index 0378691a8d..bcc72a259b 100644 --- a/vlib/os/bare/bare.S +++ b/vlib/os/bare/bare.S @@ -1,6 +1,6 @@ .intel_syntax noprefix .text - .globl _start, main__syscall5 + .globl _start, syscall5 _start: xor rbp,rbp @@ -16,7 +16,7 @@ ret /* should never be reached, but if the OS somehow fails to kill us, it will cause a segmentation fault */ - main__syscall5: + syscall5: mov rax,rdi mov rdi,rsi mov rsi,rdx diff --git a/vlib/os/bare/bare.v b/vlib/os/bare/bare.v index deacb9313a..27f08ada78 100644 --- a/vlib/os/bare/bare.v +++ b/vlib/os/bare/bare.v @@ -1,16 +1,4 @@ -fn syscall5(number, arg1, arg2, arg3, arg4, arg5 voidptr) voidptr - -fn write(fd int, data voidptr, nbytes u64) int { - return syscall5( - 1, // SYS_write - fd, - data, - nbytes, - 0, // ignored - 0 // ignored - ) -} - fn main() { - write(1, "hallo\n", 6) + write(1, c'Hello!\n', 7) + println('println test\n') }