C string literals (c'str'); bare builtin module; bare println()

pull/2773/head
Alexander Medvednikov 2019-11-15 02:04:40 +03:00
parent 0b3b241258
commit 96cde10696
7 changed files with 106 additions and 20 deletions

View File

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

View File

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

View File

@ -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'
}

View File

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

View File

@ -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 {

View File

@ -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

View File

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