run vfmt on vlib/builtin

pull/3153/head
Alexander Medvednikov 2019-12-19 23:52:45 +03:00
parent 76c800ffb6
commit d082b3f4b9
15 changed files with 839 additions and 492 deletions

View File

@ -454,7 +454,6 @@ pub fn (a []int) reduce(iter fn(accum, curr int)int, accum_start int) int {
// array_eq<T> checks if two arrays contain all the same elements in the same order. // array_eq<T> checks if two arrays contain all the same elements in the same order.
// []int == []int (also for: i64, f32, f64, byte, string) // []int == []int (also for: i64, f32, f64, byte, string)
fn array_eq<T>(a1, a2 []T) bool { fn array_eq<T>(a1, a2 []T) bool {
if a1.len != a2.len { if a1.len != a2.len {
return false return false
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
__global g_m2_buf byteptr __global g_m2_buf byteptr
@ -11,7 +10,8 @@ fn init() {
$if windows { $if windows {
if is_atty(0) > 0 { if is_atty(0) > 0 {
C._setmode(C._fileno(C.stdin), C._O_U16TEXT) C._setmode(C._fileno(C.stdin), C._O_U16TEXT)
} else { }
else {
C._setmode(C._fileno(C.stdin), C._O_U8TEXT) C._setmode(C._fileno(C.stdin), C._O_U8TEXT)
} }
C._setmode(C._fileno(C.stdout), C._O_U8TEXT) C._setmode(C._fileno(C.stdout), C._O_U8TEXT)
@ -36,18 +36,23 @@ fn on_panic(f fn (int) int) {
pub fn print_backtrace_skipping_top_frames(skipframes int) { pub fn print_backtrace_skipping_top_frames(skipframes int) {
$if windows { $if windows {
$if msvc { $if msvc {
if print_backtrace_skipping_top_frames_msvc(skipframes) { return } if print_backtrace_skipping_top_frames_msvc(skipframes) {
return
}
} }
$if mingw { $if mingw {
if print_backtrace_skipping_top_frames_mingw(skipframes) { return } if print_backtrace_skipping_top_frames_mingw(skipframes) {
return
}
} }
} $else { } $else {
if print_backtrace_skipping_top_frames_nix(skipframes) { return } if print_backtrace_skipping_top_frames_nix(skipframes) {
return
}
} }
println('print_backtrace_skipping_top_frames is not implemented on this platform for now...\n') println('print_backtrace_skipping_top_frames is not implemented on this platform for now...\n')
} }
pub fn print_backtrace() { pub fn print_backtrace() {
// at the time of backtrace_symbols_fd call, the C stack would look something like this: // at the time of backtrace_symbols_fd call, the C stack would look something like this:
// 1 frame for print_backtrace_skipping_top_frames // 1 frame for print_backtrace_skipping_top_frames
@ -99,7 +104,6 @@ pub fn print(s string) {
} }
} }
__global total_m i64=0 __global total_m i64=0
__global nr_mallocs int=0 __global nr_mallocs int=0
@ -133,6 +137,7 @@ TODO
print_backtrace() print_backtrace()
#endif #endif
*/ */
} }
pub fn calloc(n int) byteptr { pub fn calloc(n int) byteptr {
@ -166,3 +171,4 @@ pub fn is_atty(fd int) int {
return C.isatty(fd) return C.isatty(fd)
} }
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
pub fn println(s string) { pub fn println(s string) {
@ -20,9 +19,15 @@ fn print_backtrace_skipping_top_frames_mingw(skipframes int) bool {
fn print_backtrace_skipping_top_frames_nix(xskipframes int) bool { fn print_backtrace_skipping_top_frames_nix(xskipframes int) bool {
skipframes := xskipframes + 2 skipframes := xskipframes + 2
$if macos { return print_backtrace_skipping_top_frames_mac(skipframes) } $if macos {
$if linux { return print_backtrace_skipping_top_frames_linux(skipframes) } return print_backtrace_skipping_top_frames_mac(skipframes)
$if freebsd { return print_backtrace_skipping_top_frames_freebsd(skipframes) } }
$if linux {
return print_backtrace_skipping_top_frames_linux(skipframes)
}
$if freebsd {
return print_backtrace_skipping_top_frames_freebsd(skipframes)
}
return false return false
} }
@ -51,25 +56,27 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
println('TODO: print_backtrace_skipping_top_frames_linux $skipframes with tcc fails tests with "stack smashing detected" .') println('TODO: print_backtrace_skipping_top_frames_linux $skipframes with tcc fails tests with "stack smashing detected" .')
return false return false
} }
$if !android { // backtrace is not available on Android. $if !android {
// backtrace is not available on Android.
$if glibc { $if glibc {
buffer := [100]byteptr buffer := [100]byteptr
nr_ptrs := C.backtrace(*voidptr(buffer), 100) nr_ptrs := C.backtrace(*voidptr(buffer), 100)
nr_actual_frames := nr_ptrs - skipframes nr_actual_frames := nr_ptrs - skipframes
mut sframes := []string mut sframes := []string
csymbols := C.backtrace_symbols(*voidptr(&buffer[skipframes]), csymbols := C.backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
nr_actual_frames) for i in 0 .. nr_actual_frames {
for i in 0..nr_actual_frames { sframes << tos2(csymbols[i]) } sframes << tos2(csymbols[i])
}
for sframe in sframes { for sframe in sframes {
executable := sframe.all_before('(') executable := sframe.all_before('(')
addr := sframe.all_after('[').all_before(']') addr := sframe.all_after('[').all_before(']')
beforeaddr := sframe.all_before('[') beforeaddr := sframe.all_before('[')
cmd := 'addr2line -e $executable $addr' cmd := 'addr2line -e $executable $addr'
// taken from os, to avoid depending on the os module inside builtin.v // taken from os, to avoid depending on the os module inside builtin.v
f := C.popen(cmd.str, 'r') f := C.popen(cmd.str, 'r')
if isnil(f) { if isnil(f) {
println(sframe) continue println(sframe)
continue
} }
buf := [1000]byte buf := [1000]byte
mut output := '' mut output := ''
@ -78,9 +85,12 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
} }
output = output.trim_space() + ':' output = output.trim_space() + ':'
if 0 != C.pclose(f) { if 0 != C.pclose(f) {
println(sframe) continue println(sframe)
continue
}
if output in ['??:0:', '??:?:'] {
output = ''
} }
if output in ['??:0:','??:?:'] { output = '' }
println('${output:-46s} | ${addr:14s} | $beforeaddr') println('${output:-46s} | ${addr:14s} | $beforeaddr')
} }
// C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_actual_frames, 1) // C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_actual_frames, 1)
@ -92,3 +102,4 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
} }
return false return false
} }

View File

@ -1,166 +1,403 @@
module builtin module builtin
// <string.h> // <string.h>
fn C.memcpy(byteptr, byteptr, int) voidptr fn C.memcpy(byteptr, byteptr, int) voidptr
fn C.memmove(byteptr, byteptr, int) voidptr
fn C.memmove(byteptr, byteptr, int) voidptr
// fn C.malloc(int) byteptr // fn C.malloc(int) byteptr
fn C.realloc(a byteptr, b int) byteptr fn C.realloc(a byteptr, b int) byteptr
fn C.qsort(voidptr, int, int, voidptr) fn C.qsort(voidptr, int, int, voidptr)
fn C.sprintf(a ...voidptr) byteptr
fn C.strlen(s byteptr) int
fn C.isdigit(s byteptr) bool
fn C.sprintf(a ...voidptr) byteptr
fn C.strlen(s byteptr) int
fn C.isdigit(s byteptr) bool
// stdio.h // stdio.h
fn C.popen(c byteptr, t byteptr) voidptr fn C.popen(c byteptr, t byteptr) voidptr
// <execinfo.h> // <execinfo.h>
fn backtrace(a voidptr, b int) int fn backtrace(a voidptr, b int) int
fn backtrace_symbols(voidptr, int) &byteptr
fn backtrace_symbols_fd(voidptr, int, int)
fn backtrace_symbols(voidptr, int) &byteptr
fn backtrace_symbols_fd(voidptr, int, int)
// <libproc.h> // <libproc.h>
fn proc_pidpath(int, voidptr, int) int fn proc_pidpath(int, voidptr, int) int
fn C.realpath(byteptr, byteptr) &char fn C.realpath(byteptr, byteptr) &char
fn C.chmod(byteptr, int) int fn C.chmod(byteptr, int) int
fn C.printf(byteptr, ...byteptr) int fn C.printf(byteptr, ...byteptr) int
fn C.fputs(byteptr) int fn C.fputs(byteptr) int
fn C.fflush(byteptr) int fn C.fflush(byteptr) int
// TODO define args in these functions // TODO define args in these functions
fn C.fseek() int fn C.fseek() int
fn C.fopen() voidptr fn C.fopen() voidptr
fn C.fwrite() int fn C.fwrite() int
fn C.fclose() int fn C.fclose() int
fn C.pclose() int fn C.pclose() int
fn C.system() int fn C.system() int
fn C.setenv() int fn C.setenv() int
fn C.unsetenv() int fn C.unsetenv() int
fn C.access() int fn C.access() int
fn C.remove() int fn C.remove() int
fn C.rmdir() int fn C.rmdir() int
fn C.chdir() int fn C.chdir() int
fn C.fread() int fn C.fread() int
fn C.rewind() int fn C.rewind() int
fn C.stat() int fn C.stat() int
fn C.lstat() int fn C.lstat() int
fn C.rename() int fn C.rename() int
fn C.fgets() int fn C.fgets() int
fn C.memset() int fn C.memset() int
fn C.sigemptyset() int fn C.sigemptyset() int
fn C.getcwd() int fn C.getcwd() int
fn C.signal() int fn C.signal() int
fn C.mktime() int fn C.mktime() int
fn C.gettimeofday() int fn C.gettimeofday() int
fn C.sleep() int fn C.sleep() int
fn C.usleep() int fn C.usleep() int
fn C.opendir() voidptr fn C.opendir() voidptr
fn C.closedir() int fn C.closedir() int
fn C.mkdir() int fn C.mkdir() int
fn C.srand() int fn C.srand() int
fn C.atof() int fn C.atof() int
fn C.tolower() int fn C.tolower() int
fn C.toupper() int fn C.toupper() int
fn C.getchar() int fn C.getchar() int
fn C.strerror() charptr fn C.strerror() charptr
fn C.snprintf() int fn C.snprintf() int
fn C.fprintf(byteptr, ...byteptr) fn C.fprintf(byteptr, ...byteptr)
fn C.WIFEXITED() bool fn C.WIFEXITED() bool
fn C.WEXITSTATUS() int fn C.WEXITSTATUS() int
fn C.WIFSIGNALED() bool fn C.WIFSIGNALED() bool
fn C.WTERMSIG() int fn C.WTERMSIG() int
fn C.DEFAULT_LE() bool fn C.DEFAULT_LE() bool
fn C.DEFAULT_EQ() bool fn C.DEFAULT_EQ() bool
fn C.DEFAULT_GT() bool fn C.DEFAULT_GT() bool
fn C.DEFAULT_EQUAL() bool fn C.DEFAULT_EQUAL() bool
fn C.DEFAULT_NOT_EQUAL() bool fn C.DEFAULT_NOT_EQUAL() bool
fn C.DEFAULT_LT() bool fn C.DEFAULT_LT() bool
fn C.DEFAULT_GE() bool fn C.DEFAULT_GE() bool
fn C.isatty() int fn C.isatty() int
fn C.syscall() int fn C.syscall() int
fn C.sysctl() int fn C.sysctl() int
// Windows // Windows
fn C._setmode(int, int) int fn C._setmode(int, int) int
fn C._fileno(int) int fn C._fileno(int) int
fn C._get_osfhandle(fd int) C.intptr_t fn C._get_osfhandle(fd int) C.intptr_t
fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32 fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
fn C.SetHandleInformation(hObject voidptr, dwMask u32, dwFlags u32) bool fn C.SetHandleInformation(hObject voidptr, dwMask u32, dwFlags u32) bool
fn C.ExpandEnvironmentStringsW(lpSrc &u16, lpDst &u16, nSize u32) u32 fn C.ExpandEnvironmentStringsW(lpSrc &u16, lpDst &u16, nSize u32) u32
fn C.CreateProcessW(lpApplicationName &u16, lpCommandLine &u16, lpProcessAttributes voidptr, lpThreadAttributes voidptr, bInheritHandles bool, dwCreationFlags u32, lpEnvironment voidptr, lpCurrentDirectory &u16, lpStartupInfo voidptr, lpProcessInformation voidptr) bool fn C.CreateProcessW(lpApplicationName &u16, lpCommandLine &u16, lpProcessAttributes voidptr, lpThreadAttributes voidptr, bInheritHandles bool, dwCreationFlags u32, lpEnvironment voidptr, lpCurrentDirectory &u16, lpStartupInfo voidptr, lpProcessInformation voidptr) bool
fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumberOfBytesRead voidptr, lpOverlapped voidptr) bool fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumberOfBytesRead voidptr, lpOverlapped voidptr) bool
fn C.GetFileAttributesW(lpFileName byteptr) u32 fn C.GetFileAttributesW(lpFileName byteptr) u32
fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int
fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int
fn C.RegCloseKey() fn C.RegCloseKey()
fn C.RegQueryValueEx() voidptr fn C.RegQueryValueEx() voidptr
fn C.RemoveDirectory() int fn C.RemoveDirectory() int
fn C.GetStdHandle() voidptr fn C.GetStdHandle() voidptr
fn C.SetConsoleMode() fn C.SetConsoleMode()
fn C.GetConsoleMode() int fn C.GetConsoleMode() int
fn C._putws() fn C._putws()
fn C.wprintf() fn C.wprintf()
fn C.setbuf() fn C.setbuf()
fn C.SymCleanup() fn C.SymCleanup()
fn C.MultiByteToWideChar() int fn C.MultiByteToWideChar() int
fn C.wcslen() int fn C.wcslen() int
fn C.WideCharToMultiByte() int fn C.WideCharToMultiByte() int
fn C._wstat() fn C._wstat()
fn C._wrename() fn C._wrename()
fn C._wfopen() voidptr fn C._wfopen() voidptr
fn C._wpopen() voidptr fn C._wpopen() voidptr
fn C._pclose() int fn C._pclose() int
fn C._wsystem() int fn C._wsystem() int
fn C._wgetenv() voidptr fn C._wgetenv() voidptr
fn C._putenv() int fn C._putenv() int
fn C._waccess() int fn C._waccess() int
fn C._wremove() fn C._wremove()
fn C.ReadConsole() fn C.ReadConsole()
fn C.fgetws() voidptr fn C.fgetws() voidptr
fn C.GetModuleFileName() int fn C.GetModuleFileName() int
fn C._wchdir() fn C._wchdir()
fn C._wgetcwd() int fn C._wgetcwd() int
fn C._fullpath() int fn C._fullpath() int
fn C.GetCommandLine() voidptr fn C.GetCommandLine() voidptr
fn C.CommandLineToArgvW() &voidptr fn C.CommandLineToArgvW() &voidptr
fn C.LocalFree() fn C.LocalFree()
fn C.FindFirstFileW() voidptr fn C.FindFirstFileW() voidptr
fn C.FindFirstFile() voidptr fn C.FindFirstFile() voidptr
fn C.FindNextFile() voidptr fn C.FindNextFile() voidptr
fn C.FindClose() fn C.FindClose()
fn C.MAKELANGID() int fn C.MAKELANGID() int
fn C.FormatMessage() voidptr fn C.FormatMessage() voidptr
fn C.CloseHandle() fn C.CloseHandle()
fn C.GetExitCodeProcess() fn C.GetExitCodeProcess()
fn C.RegOpenKeyEx() voidptr fn C.RegOpenKeyEx() voidptr
fn C.GetTickCount() i64 fn C.GetTickCount() i64
fn C.Sleep() fn C.Sleep()
fn C.WSAStartup(u16, &voidptr) int fn C.WSAStartup(u16, &voidptr) int
fn C.WSAGetLastError() int fn C.WSAGetLastError() int
fn C.closesocket(int) int fn C.closesocket(int) int
fn C.vschannel_init(&C.TlsContext) fn C.vschannel_init(&C.TlsContext)
fn C.request(&C.TlsContext, int, &u16, byteptr, &byteptr) fn C.request(&C.TlsContext, int, &u16, byteptr, &byteptr)
fn C.vschannel_cleanup(&C.TlsContext) fn C.vschannel_cleanup(&C.TlsContext)
fn C.URLDownloadToFile(int, &u16, &u16, int, int) fn C.URLDownloadToFile(int, &u16, &u16, int, int)
fn C.GetLastError() u32 fn C.GetLastError() u32
fn C.CreateDirectory(byteptr, int) bool fn C.CreateDirectory(byteptr, int) bool
fn C.BCryptGenRandom(int, voidptr, int, int) int fn C.BCryptGenRandom(int, voidptr, int, int) int
fn C.CreateMutex(int, bool, byteptr) voidptr fn C.CreateMutex(int, bool, byteptr) voidptr
fn C.WaitForSingleObject(voidptr, int) int fn C.WaitForSingleObject(voidptr, int) int
fn C.ReleaseMutex(voidptr) bool fn C.ReleaseMutex(voidptr) bool

View File

@ -143,3 +143,4 @@ fn (a f64) gebit(b f64) bool {
fn (a f32) gebit(b f32) bool { fn (a f32) gebit(b f32) bool {
return C.DEFAULT_GE(a, b) return C.DEFAULT_GE(a, b)
} }

View File

@ -1,9 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
/* /*
This is work in progress. This is work in progress.
A very early test version of the hashmap with a fixed size. A very early test version of the hashmap with a fixed size.
@ -14,6 +12,7 @@ module builtin
the performance gains are basically non-existent. the performance gains are basically non-existent.
*/ */
struct hashmap { struct hashmap {
cap int cap int
keys []string keys []string
@ -60,9 +59,12 @@ fn (m mut hashmap) set(key string, val int) {
for e.next != 0 { for e.next != 0 {
e = e.next e = e.next
} }
e.next = &hashmapentry{key, val, 0} e.next = &hashmapentry{
} else { key,val,0}
m.table[idx] = hashmapentry{key, val, 0} }
else {
m.table[idx] = hashmapentry{
key,val,0}
} }
} }
@ -70,7 +72,8 @@ fn (m mut hashmap) get(key string) int {
hash := int(b_fabs(key.hash())) hash := int(b_fabs(key.hash()))
idx := hash % m.cap idx := hash % m.cap
mut e := &m.table[idx] mut e := &m.table[idx]
for e.next != 0 { // todo unsafe { for e.next != 0 {
// todo unsafe {
if e.key == key { if e.key == key {
return e.val return e.val
} }
@ -79,4 +82,8 @@ fn (m mut hashmap) get(key string) int {
return e.val return e.val
} }
[inline] fn b_fabs(v int) f64 { return if v < 0 { -v } else { v } } [inline]
fn b_fabs(v int) f64 {
return if v < 0 { -v } else { v }
}

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
pub fn ptr_str(ptr voidptr) string { pub fn ptr_str(ptr voidptr) string {
@ -42,9 +41,17 @@ pub fn (nn int) str() string {
return tos(buf + max - len, len) return tos(buf + max - len, len)
} }
pub fn (n i8) str() string { return int(n).str() } pub fn (n i8) str() string {
pub fn (n i16) str() string { return int(n).str() } return int(n).str()
pub fn (n u16) str() string { return int(n).str() } }
pub fn (n i16) str() string {
return int(n).str()
}
pub fn (n u16) str() string {
return int(n).str()
}
pub fn (nn u32) str() string { pub fn (nn u32) str() string {
mut n := nn mut n := nn
@ -84,6 +91,7 @@ pub fn (nn byte) str() string {
} }
*/ */
pub fn (nn i64) str() string { pub fn (nn i64) str() string {
mut n := nn mut n := nn
if n == i64(0) { if n == i64(0) {
@ -138,22 +146,14 @@ pub fn (b bool) str() string {
} }
pub fn (n int) hex() string { pub fn (n int) hex() string {
len := if n >= 0 { len := if n >= 0 { n.str().len + 3 } else { 11 }
n.str().len + 3
} else {
11
}
hex := malloc(len) // 0x + \n hex := malloc(len) // 0x + \n
count := int(C.sprintf(charptr(hex), '0x%x', n)) count := int(C.sprintf(charptr(hex), '0x%x', n))
return tos(hex, count) return tos(hex, count)
} }
pub fn (n i64) hex() string { pub fn (n i64) hex() string {
len := if n >= i64(0) { len := if n >= i64(0) { n.str().len + 3 } else { 19 }
n.str().len + 3
} else {
19
}
hex := malloc(len) hex := malloc(len)
count := int(C.sprintf(charptr(hex), '0x%'C.PRIx64, n)) count := int(C.sprintf(charptr(hex), '0x%'C.PRIx64, n))
return tos(hex, count) return tos(hex, count)

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
import strings import strings
@ -65,7 +64,8 @@ fn (m mut map) insert(n mut mapnode, key string, val voidptr) {
if n.left == 0 { if n.left == 0 {
n.left = new_node(key, val, m.element_size) n.left = new_node(key, val, m.element_size)
m.size++ m.size++
} else { }
else {
m.insert(mut n.left, key, val) m.insert(mut n.left, key, val)
} }
return return
@ -73,7 +73,8 @@ fn (m mut map) insert(n mut mapnode, key string, val voidptr) {
if n.right == 0 { if n.right == 0 {
n.right = new_node(key, val, m.element_size) n.right = new_node(key, val, m.element_size)
m.size++ m.size++
} else { }
else {
m.insert(mut n.right, key, val) m.insert(mut n.right, key, val)
} }
} }
@ -86,14 +87,16 @@ fn (n & mapnode) find(key string, out voidptr, element_size int) bool{
else if n.key > key { else if n.key > key {
if n.left == 0 { if n.left == 0 {
return false return false
} else { }
else {
return n.left.find(key, out, element_size) return n.left.find(key, out, element_size)
} }
} }
else { else {
if n.right == 0 { if n.right == 0 {
return false return false
} else { }
else {
return n.right.find(key, out, element_size) return n.right.find(key, out, element_size)
} }
} }
@ -107,14 +110,16 @@ fn (n & mapnode) find2(key string, element_size int) bool{
else if n.key > key { else if n.key > key {
if isnil(n.left) { if isnil(n.left) {
return false return false
} else { }
else {
return n.left.find2(key, element_size) return n.left.find2(key, element_size)
} }
} }
else { else {
if isnil(n.right) { if isnil(n.right) {
return false return false
} else { }
else {
return n.right.find2(key, element_size) return n.right.find2(key, element_size)
} }
} }
@ -156,6 +161,7 @@ fn (m map) bs(query string, start, end int, out voidptr) {
} }
*/ */
fn preorder_keys(node &mapnode, keys mut []string, key_i int) int { fn preorder_keys(node &mapnode, keys mut []string, key_i int) int {
mut i := key_i mut i := key_i
if !node.is_empty { if !node.is_empty {
@ -197,14 +203,16 @@ pub fn (n mut mapnode) delete(key string, element_size int) {
else if n.key > key { else if n.key > key {
if isnil(n.left) { if isnil(n.left) {
return return
} else { }
else {
n.left.delete(key, element_size) n.left.delete(key, element_size)
} }
} }
else { else {
if isnil(n.right) { if isnil(n.right) {
return return
} else { }
else {
n.right.delete(key, element_size) n.right.delete(key, element_size)
} }
} }
@ -235,6 +243,7 @@ pub fn (m map) print() {
println('') println('')
} }
*/ */
println('>>>>>>>>>>') println('>>>>>>>>>>')
} }
@ -272,3 +281,4 @@ pub fn (m map_string) str() string {
sb.writeln('}') sb.writeln('}')
return sb.str() return sb.str()
} }

View File

@ -1,9 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
/* /*
struct Option2<T> { struct Option2<T> {
data T data T
@ -14,6 +12,7 @@ struct Option2<T> {
} }
*/ */
struct Option { struct Option {
data [300]byte data [300]byte
error string error string
@ -36,7 +35,9 @@ fn opt_ok(data voidptr, size int) Option {
// used internally when returning `none` // used internally when returning `none`
fn opt_none() Option { fn opt_none() Option {
return Option{ is_none: true } return Option{
is_none: true
}
} }
pub fn error(s string) Option { pub fn error(s string) Option {
@ -52,5 +53,3 @@ pub fn error_with_code(s string, code int) Option {
} }
} }

View File

@ -1,11 +1,9 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
import strconv import strconv
/* /*
NB: A V string should be/is immutable from the point of view of NB: A V string should be/is immutable from the point of view of
V user programs after it is first created. A V string is V user programs after it is first created. A V string is
@ -134,7 +132,9 @@ pub fn cstring_to_vstring(cstr byteptr) string {
} }
pub fn (s string) replace_once(rep, with string) string { pub fn (s string) replace_once(rep, with string) string {
index := s.index(rep) or { return s } index := s.index(rep) or {
return s
}
return s.substr(0, index) + with + s.substr(index + rep.len, s.len) return s.substr(0, index) + with + s.substr(index + rep.len, s.len)
} }
@ -199,7 +199,6 @@ fn (a mut []RepIndex) sort() {
a.sort_with_compare(compare_rep_index) a.sort_with_compare(compare_rep_index)
} }
// TODO // TODO
/* /*
fn (a RepIndex) < (b RepIndex) bool { fn (a RepIndex) < (b RepIndex) bool {
@ -207,6 +206,7 @@ fn (a RepIndex) < (b RepIndex) bool {
} }
*/ */
fn compare_rep_index(a, b &RepIndex) int { fn compare_rep_index(a, b &RepIndex) int {
if a.idx < b.idx { if a.idx < b.idx {
return -1 return -1
@ -243,7 +243,8 @@ pub fn (s string) replace_each(vals []string) string {
} }
// We need to remember both the position in the string, // We need to remember both the position in the string,
// and which rep/with pair it refers to. // and which rep/with pair it refers to.
idxs << RepIndex{idx, rep_i} idxs << RepIndex{
idx,rep_i}
idx++ idx++
new_len += with.len - rep.len new_len += with.len - rep.len
} }
@ -317,7 +318,8 @@ pub fn (s string) u64() u64 {
// == // ==
fn (s string) eq(a string) bool { fn (s string) eq(a string) bool {
if isnil(s.str) { // should never happen if isnil(s.str) {
// should never happen
panic('string.eq(): nil string') panic('string.eq(): nil string')
} }
if s.len != a.len { if s.len != a.len {
@ -412,7 +414,9 @@ pub fn (s string) split_nth(delim string, nth int) []string {
j++ j++
} }
was_last := nth > 0 && res.len == nth was_last := nth > 0 && res.len == nth
if was_last{break} if was_last {
break
}
last := i == s.len - 1 last := i == s.len - 1
if is_delim || last { if is_delim || last {
if !is_delim && last { if !is_delim && last {
@ -460,6 +464,7 @@ fn (s string) left(n int) string {
} }
return s.substr(0, n) return s.substr(0, n)
} }
// 'hello'.right(2) => 'llo' // 'hello'.right(2) => 'llo'
fn (s string) right(n int) string { fn (s string) right(n int) string {
if n >= s.len { if n >= s.len {
@ -479,7 +484,6 @@ fn (s string) substr(start, end int) string {
panic('substr($start, $end) out of bounds (len=$s.len)') panic('substr($start, $end) out of bounds (len=$s.len)')
} }
len := end - start len := end - start
mut res := string{ mut res := string{
len: len len: len
str: malloc(len + 1) str: malloc(len + 1)
@ -488,13 +492,13 @@ fn (s string) substr(start, end int) string {
res.str[i] = s.str[start + i] res.str[i] = s.str[start + i]
} }
res.str[len] = `\0` res.str[len] = `\0`
/* /*
res := string { res := string {
str: s.str + start str: s.str + start
len: len len: len
} }
*/ */
return res return res
} }
@ -565,10 +569,11 @@ fn (s string) index_kmp(p string) int {
return -1 return -1
} }
pub fn (s string) index_any(chars string) int { pub fn (s string) index_any(chars string) int {
for c in chars { for c in chars {
index := s.index(c.str()) or { continue } index := s.index(c.str()) or {
continue
}
return index return index
} }
return -1 return -1
@ -666,7 +671,9 @@ pub fn (s string) contains(p string) bool {
} }
pub fn (s string) starts_with(p string) bool { pub fn (s string) starts_with(p string) bool {
idx := s.index(p) or { return false } idx := s.index(p) or {
return false
}
return idx == 0 return idx == 0
} }
@ -706,22 +713,24 @@ pub fn (s string) capitalize() string {
pub fn (s string) title() string { pub fn (s string) title() string {
words := s.split(' ') words := s.split(' ')
mut tit := []string mut tit := []string
for word in words { for word in words {
tit << word.capitalize() tit << word.capitalize()
} }
title := tit.join(' ') title := tit.join(' ')
return title return title
} }
// 'hey [man] how you doin' // 'hey [man] how you doin'
// find_between('[', ']') == 'man' // find_between('[', ']') == 'man'
pub fn (s string) find_between(start, end string) string { pub fn (s string) find_between(start, end string) string {
start_pos := s.index(start) or { return '' } start_pos := s.index(start) or {
return ''
}
// First get everything to the right of 'start' // First get everything to the right of 'start'
val := s.right(start_pos + start.len) val := s.right(start_pos + start.len)
end_pos := val.index(end) or { return val } end_pos := val.index(end) or {
return val
}
return val.left(end_pos) return val.left(end_pos)
} }
@ -756,6 +765,7 @@ pub fn (a []string) to_c() voidptr {
} }
*/ */
pub fn (c byte) is_space() bool { pub fn (c byte) is_space() bool {
return c in [` `, `\n`, `\t`, `\v`, `\f`, `\r`] return c in [` `, `\n`, `\t`, `\v`, `\f`, `\r`]
} }
@ -859,6 +869,7 @@ pub fn (s string) ustring() ustring {
s: s s: s
// runes will have at least s.len elements, save reallocations // runes will have at least s.len elements, save reallocations
// TODO use VLA for small strings? // TODO use VLA for small strings?
runes: new_array(0, s.len, sizeof(int)) runes: new_array(0, s.len, sizeof(int))
} }
for i := 0; i < s.len; i++ { for i := 0; i < s.len; i++ {
@ -874,6 +885,7 @@ pub fn (s string) ustring() ustring {
// It's called from functions like draw_text() where we know that the string is going to be freed // It's called from functions like draw_text() where we know that the string is going to be freed
// right away. Uses global buffer for storing runes []int array. // right away. Uses global buffer for storing runes []int array.
__global g_ustring_runes []int __global g_ustring_runes []int
pub fn (s string) ustring_tmp() ustring { pub fn (s string) ustring_tmp() ustring {
if g_ustring_runes.len == 0 { if g_ustring_runes.len == 0 {
g_ustring_runes = new_array(0, 128, sizeof(int)) g_ustring_runes = new_array(0, 128, sizeof(int))
@ -996,12 +1008,7 @@ pub fn (u ustring) substr(_start, _end int) string {
if _start > _end || _start > u.len || _end > u.len || _start < 0 || _end < 0 { if _start > _end || _start > u.len || _end > u.len || _start < 0 || _end < 0 {
panic('substr($_start, $_end) out of bounds (len=$u.len)') panic('substr($_start, $_end) out of bounds (len=$u.len)')
} }
end := if _end >= u.len { end := if _end >= u.len { u.s.len } else { u.runes[_end] }
u.s.len
}
else {
u.runes[_end]
}
return u.s.substr(u.runes[_start], end) return u.s.substr(u.runes[_start], end)
} }
@ -1068,7 +1075,9 @@ fn (arr []string) free() {
// all_before('23:34:45.234', '.') == '23:34:45' // all_before('23:34:45.234', '.') == '23:34:45'
pub fn (s string) all_before(dot string) string { pub fn (s string) all_before(dot string) string {
pos := s.index(dot) or { return s } pos := s.index(dot) or {
return s
}
return s.left(pos) return s.left(pos)
} }
@ -1158,7 +1167,6 @@ pub fn (c byte) is_white() bool {
return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r` return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r`
} }
pub fn (s string) hash() int { pub fn (s string) hash() int {
// mut h := s.hash_cache // mut h := s.hash_cache
mut h := 0 mut h := 0
@ -1193,3 +1201,4 @@ pub fn (s string) repeat(count int) string {
ret[s.len * count] = 0 ret[s.len * count] = 0
return string(ret) return string(ret)
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module builtin module builtin
pub fn utf8_char_len(b byte) int { pub fn utf8_char_len(b byte) int {
@ -19,20 +18,29 @@ pub fn utf32_to_str(code u32) string {
} }
if (icode <= 2047/* 0x7FF */) { if (icode <= 2047/* 0x7FF */) {
buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */ buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */
buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 2) return tos(buffer, 2)
} }
if (icode <= 65535/* 0xFFFF */) { if (icode <= 65535/* 0xFFFF */) {
buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */ buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */
buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 3) return tos(buffer, 3)
} }
if (icode <= 1114111/* 0x10FFFF */) { if (icode <= 1114111/* 0x10FFFF */) {
buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */ buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */
buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */
buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 4) return tos(buffer, 4)
} }
return '' return ''
@ -48,20 +56,29 @@ pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string {
} }
if (icode <= 2047/* 0x7FF */) { if (icode <= 2047/* 0x7FF */) {
buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */ buffer[0] = 192/*0xC0*/ | (icode>>6)/* 110xxxxx */
buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 2) return tos(buffer, 2)
} }
if (icode <= 65535/* 0xFFFF */) { if (icode <= 65535/* 0xFFFF */) {
buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */ buffer[0] = 224/*0xE0*/ | (icode>>12)/* 1110xxxx */
buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[2] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 3) return tos(buffer, 3)
} }
if (icode <= 1114111/* 0x10FFFF */) { if (icode <= 1114111/* 0x10FFFF */) {
buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */ buffer[0] = 240/*0xF0*/ | (icode>>18)/* 11110xxx */
buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */ buffer[1] = 128/*0x80*/ | ((icode>>12) & 63/*0x3F*/)/* 10xxxxxx */
buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */ buffer[2] = 128/*0x80*/ | ((icode>>6) & 63/*0x3F*/)/* 10xxxxxx */
buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */ buffer[3] = 128/*0x80*/ | (icode & 63/*0x3F*/)/* 10xxxxxx */
return tos(buffer, 4) return tos(buffer, 4)
} }
return '' return ''
@ -136,18 +153,22 @@ pub fn string_from_wide2(_wstr &u16, len int) string {
fn utf8_len(c byte) int { fn utf8_len(c byte) int {
mut b := 0 mut b := 0
mut x := c mut x := c
if ((x & 240) != 0) {
if ((x & 240) != 0) { //0xF0 // 0xF0
x >>= 4 x >>= 4
} else { }
else {
b += 4 b += 4
} }
if ((x & 12) != 0) { //0x0C if ((x & 12) != 0) {
// 0x0C
x >>= 2 x >>= 2
} else { }
else {
b += 2 b += 2
} }
if ((x & 2) == 0) { //0x02 if ((x & 2) == 0) {
// 0x02
b++ b++
} }
return b return b
@ -159,23 +180,29 @@ pub fn utf8_getchar() int {
len := utf8_len(~c) len := utf8_len(~c)
if c < 0 { if c < 0 {
return 0 return 0
} else if len == 0 { }
else if len == 0 {
return c return c
} else if len == 1 { }
else if len == 1 {
return -1 return -1
} else { }
else {
mut uc := c & ((1<<(7 - len)) - 1) mut uc := c & ((1<<(7 - len)) - 1)
for i := 0; i + 1 < len; i++ { for i := 0; i + 1 < len; i++ {
c2 := C.getchar() c2 := C.getchar()
if c2 != -1 && (c2>>6) == 2 { if c2 != -1 && (c2>>6) == 2 {
uc <<= 6 uc <<= 6
uc |= (c2 & 63) uc |= (c2 & 63)
} else if c2 == -1 { }
else if c2 == -1 {
return 0 return 0
} else { }
else {
return -1 return -1
} }
} }
return uc return uc
} }
} }

View File

@ -3,8 +3,6 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module compiler module compiler
import ( import (
strings strings
) )

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module compiler module compiler
import strings import strings
@ -9,14 +8,15 @@ import strings
const ( const (
dot_ptr = '->' dot_ptr = '->'
) )
// returns the type of the new variable // returns the type of the new variable
fn (p mut Parser) gen_var_decl(name string, is_static bool) string { fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
p.is_var_decl = true p.is_var_decl = true
mut typ := p.bool_expression() mut typ := p.bool_expression()
// mut typ, expr := p.tmp_expr() // mut typ, expr := p.tmp_expr()
p.is_var_decl = false p.is_var_decl = false
if typ.starts_with('...') { typ = typ[3..] } if typ.starts_with('...') {
typ = typ[3..]
}
// p.gen('/*after expr*/') // p.gen('/*after expr*/')
// Option check ? or { // Option check ? or {
or_else := p.tok == .key_orelse or_else := p.tok == .key_orelse
@ -28,17 +28,18 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
// `foo := C.Foo{}` => `Foo foo;` // `foo := C.Foo{}` => `Foo foo;`
if !p.is_empty_c_struct_init && !typ.starts_with('[') { if !p.is_empty_c_struct_init && !typ.starts_with('[') {
nt_gen += '=' nt_gen += '='
} else if typ.starts_with('[') && typ[ typ.len-1 ] != `*` { }
else if typ.starts_with('[') && typ[typ.len - 1] != `*` {
// a fixed_array initializer, like `v := [1.1, 2.2]!!` // a fixed_array initializer, like `v := [1.1, 2.2]!!`
// ... should translate to the following in C `f32 v[2] = {1.1, 2.2};` // ... should translate to the following in C `f32 v[2] = {1.1, 2.2};`
initializer := p.cgen.cur_line initializer := p.cgen.cur_line
if initializer.len > 0 { if initializer.len > 0 {
p.cgen.resetln(' = {' + initializer.all_after('{')) p.cgen.resetln(' = {' + initializer.all_after('{'))
} else if initializer.len == 0 { }
else if initializer.len == 0 {
p.cgen.resetln(' = { 0 }') p.cgen.resetln(' = { 0 }')
} }
} }
if is_static { if is_static {
nt_gen = 'static $nt_gen' nt_gen = 'static $nt_gen'
} }
@ -50,13 +51,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
} }
fn (p mut Parser) gen_fn_decl(f Fn, typ, str_args string) { fn (p mut Parser) gen_fn_decl(f Fn, typ, str_args string) {
dll_export_linkage := if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so { dll_export_linkage := if p.pref.ccompiler == 'msvc' && p.attr == 'live' && p.pref.is_so { '__declspec(dllexport) ' } else if p.attr == 'inline' { 'static inline ' } else { '' }
'__declspec(dllexport) '
} else if p.attr == 'inline' {
'static inline '
} else {
''
}
fn_name_cgen := p.table.fn_gen_name(f) fn_name_cgen := p.table.fn_gen_name(f)
// str_args := f.str_args(p.table) // str_args := f.str_args(p.table)
p.genln('$dll_export_linkage$typ $fn_name_cgen ($str_args) {') p.genln('$dll_export_linkage$typ $fn_name_cgen ($str_args) {')
@ -82,10 +77,12 @@ fn (p mut Parser) gen_blank_identifier_assign() {
// handle or // handle or
if p.tok == .key_orelse { if p.tok == .key_orelse {
p.gen_handle_option_or_else(typ, '', pos) p.gen_handle_option_or_else(typ, '', pos)
} else { }
else {
if is_fn_call { if is_fn_call {
p.gen(';') p.gen(';')
} else { }
else {
p.cgen.resetln('{$typ _ = $p.cgen.cur_line;}') p.cgen.resetln('{$typ _ = $p.cgen.cur_line;}')
} }
} }
@ -116,7 +113,8 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
is_mut: false is_mut: false
is_used: true is_used: true
}) })
if is_assign && !name.contains('.') { // don't initialize struct fields if is_assign && !name.contains('.') {
// don't initialize struct fields
p.genln('$typ $name;') p.genln('$typ $name;')
} }
p.genln('if (!$tmp .ok) {') p.genln('if (!$tmp .ok) {')
@ -128,11 +126,7 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
// workaround for -g with default optional value // workaround for -g with default optional value
// when p.cgen.line_directives is true an extra // when p.cgen.line_directives is true an extra
// line is added so we need to account for that // line is added so we need to account for that
expr_line := if p.cgen.line_directives { expr_line := if p.cgen.line_directives { p.cgen.lines[p.cgen.lines.len - 3] } else { p.cgen.lines[p.cgen.lines.len - 2] }
p.cgen.lines[p.cgen.lines.len-3]
} else {
p.cgen.lines[p.cgen.lines.len-2]
}
last_expr := expr_line[last_ph..] last_expr := expr_line[last_ph..]
p.cgen.lines[p.cgen.lines.len - 2] = '' p.cgen.lines[p.cgen.lines.len - 2] = ''
// same here // same here
@ -144,7 +138,8 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s
p.genln('} else {') p.genln('} else {')
p.genln('$name = $last_expr') p.genln('$name = $last_expr')
p.genln('}') p.genln('}')
} else if is_assign { }
else if is_assign {
p.genln('$name = *($typ*)${tmp}.data;') p.genln('$name = *($typ*)${tmp}.data;')
} }
if !p.returns && last_typ != typ && is_assign && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break { if !p.returns && last_typ != typ && is_assign && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break {
@ -192,8 +187,7 @@ fn types_to_c(types []Type, table &Table) string {
} }
for field in t.fields { for field in t.fields {
sb.write('\t') sb.write('\t')
sb.writeln(table.cgen_name_type_pair(field.name, sb.writeln(table.cgen_name_type_pair(field.name, field.typ) + ';')
field.typ) + ';')
} }
sb.writeln('};\n') sb.writeln('};\n')
if t.cat == .objc_interface { if t.cat == .objc_interface {
@ -211,7 +205,8 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
if p.cgen.is_tmp { if p.cgen.is_tmp {
index_expr = p.cgen.tmp_line[fn_ph..] index_expr = p.cgen.tmp_line[fn_ph..]
p.cgen.resetln(p.cgen.tmp_line[..fn_ph]) p.cgen.resetln(p.cgen.tmp_line[..fn_ph])
} else { }
else {
index_expr = p.cgen.cur_line[fn_ph..] index_expr = p.cgen.cur_line[fn_ph..]
p.cgen.resetln(p.cgen.cur_line[..fn_ph]) p.cgen.resetln(p.cgen.cur_line[..fn_ph])
} }
@ -221,8 +216,7 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
if cfg.is_map { if cfg.is_map {
p.gen('$tmp') p.gen('$tmp')
def := type_default(typ) def := type_default(typ)
p.cgen.insert_before('$typ $tmp = $def; ' + p.cgen.insert_before('$typ $tmp = $def; ' + 'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
} }
else if cfg.is_arr { else if cfg.is_arr {
if p.pref.translated && !p.builtin_mod { if p.pref.translated && !p.builtin_mod {
@ -244,7 +238,8 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
} }
else if cfg.is_slice { else if cfg.is_slice {
p.gen('string_substr2($index_expr)') p.gen('string_substr2($index_expr)')
} else { }
else {
p.gen('string_at($index_expr)') p.gen('string_at($index_expr)')
} }
} }
@ -255,7 +250,6 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
// p.cgen.insert_before('if (!${tmp}.str) $tmp = tos("", 0);') // p.cgen.insert_before('if (!${tmp}.str) $tmp = tos("", 0);')
p.cgen.insert_before('if (!$tmp_ok) $tmp = tos((byte *)"", 0);') p.cgen.insert_before('if (!$tmp_ok) $tmp = tos((byte *)"", 0);')
} }
} }
fn (table mut Table) fn_gen_name(f &Fn) string { fn (table mut Table) fn_gen_name(f &Fn) string {
@ -265,13 +259,23 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
name = name.replace(' ', '') name = name.replace(' ', '')
if f.name.len == 1 { if f.name.len == 1 {
match f.name[0] { match f.name[0] {
`+` { name = name.replace('+', 'op_plus') } `+` {
`-` { name = name.replace('-', 'op_minus') } name = name.replace('+', 'op_plus')
`*` { name = name.replace('*', 'op_mul') }
`/` { name = name.replace('/', 'op_div') }
`%` { name = name.replace('%', 'op_mod') }
else {}
} }
`-` {
name = name.replace('-', 'op_minus')
}
`*` {
name = name.replace('*', 'op_mul')
}
`/` {
name = name.replace('/', 'op_div')
}
`%` {
name = name.replace('%', 'op_mod')
}
else {
}}
} }
} }
if f.is_interface { if f.is_interface {
@ -288,20 +292,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
// Obfuscate but skip certain names // Obfuscate but skip certain names
// TODO ugly, fix // TODO ugly, fix
// NB: the order here is from faster to potentially slower checks // NB: the order here is from faster to potentially slower checks
if table.obfuscate && if table.obfuscate && !f.is_c && f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' && f.name != 'gg__vec2' && f.name != 'build_token_str' && f.name != 'build_keys' && f.mod != 'builtin' && f.mod != 'darwin' && f.mod != 'os' && f.mod != 'json' && !f.name.ends_with('_init') && !f.name.contains('window_proc') && !name.ends_with('_str') && !name.contains('contains') {
!f.is_c &&
f.name != 'main' && f.name != 'WinMain' && f.name != 'main__main' &&
f.name != 'gg__vec2' &&
f.name != 'build_token_str' &&
f.name != 'build_keys' &&
f.mod != 'builtin' &&
f.mod != 'darwin' &&
f.mod != 'os' &&
f.mod != 'json' &&
!f.name.ends_with('_init') &&
!f.name.contains('window_proc') &&
!name.ends_with('_str') &&
!name.contains('contains') {
mut idx := table.obf_ids[name] mut idx := table.obf_ids[name]
// No such function yet, register it // No such function yet, register it
if idx == 0 { if idx == 0 {
@ -316,9 +307,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
return name return name
} }
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string, fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string, cgen_name string, ftyp string, method_ph int) {
cgen_name string, ftyp string, method_ph int)
{
// mut cgen_name := p.table.fn_gen_name(f) // mut cgen_name := p.table.fn_gen_name(f)
mut method_call := cgen_name + ' (' mut method_call := cgen_name + ' ('
// if receiver is key_mut or a ref (&), generate & for the first arg // if receiver is key_mut or a ref (&), generate & for the first arg
@ -337,7 +326,8 @@ fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string,
// array_int => int // array_int => int
cast = receiver_type.all_after('array_') cast = receiver_type.all_after('array_')
cast = '*($cast*) ' cast = '*($cast*) '
} else { }
else {
cast = '(voidptr) ' cast = '(voidptr) '
} }
} }
@ -372,13 +362,17 @@ fn (p mut Parser) gen_array_at(typ_ string, is_arr0 bool, fn_ph int) {
fn (p mut Parser) gen_for_header(i, tmp, var_typ, val string) { fn (p mut Parser) gen_for_header(i, tmp, var_typ, val string) {
p.genln('for (int $i = 0; $i < ${tmp}.len; $i++) {') p.genln('for (int $i = 0; $i < ${tmp}.len; $i++) {')
if val == '_' { return } if val == '_' {
return
}
p.genln('$var_typ $val = (($var_typ *) $tmp . data)[$i];') p.genln('$var_typ $val = (($var_typ *) $tmp . data)[$i];')
} }
fn (p mut Parser) gen_for_fixed_header(i, tmp, var_typ, val string) { fn (p mut Parser) gen_for_fixed_header(i, tmp, var_typ, val string) {
p.genln('for (int $i = 0; $i < sizeof(${tmp}) / sizeof($tmp [0]); $i++) {') p.genln('for (int $i = 0; $i < sizeof(${tmp}) / sizeof($tmp [0]); $i++) {')
if val == '_' { return } if val == '_' {
return
}
p.genln('$var_typ $val = $tmp[$i];') p.genln('$var_typ $val = $tmp[$i];')
} }
@ -386,14 +380,18 @@ fn (p mut Parser) gen_for_str_header(i, tmp, var_typ, val string) {
// TODO var_typ is always byte // TODO var_typ is always byte
// p.genln('array_byte bytes_$tmp = string_bytes( $tmp );') // p.genln('array_byte bytes_$tmp = string_bytes( $tmp );')
p.genln(';\nfor (int $i = 0; $i < $tmp .len; $i ++) {') p.genln(';\nfor (int $i = 0; $i < $tmp .len; $i ++) {')
if val == '_' { return } if val == '_' {
return
}
// p.genln('$var_typ $val = (($var_typ *) bytes_$tmp . data)[$i];') // p.genln('$var_typ $val = (($var_typ *) bytes_$tmp . data)[$i];')
p.genln('$var_typ $val = ${tmp}.str[$i];') p.genln('$var_typ $val = ${tmp}.str[$i];')
} }
fn (p mut Parser) gen_for_range_header(i, range_end, tmp, var_type, val string) { fn (p mut Parser) gen_for_range_header(i, range_end, tmp, var_type, val string) {
p.genln(';\nfor (int $i = $tmp; $i < $range_end; $i++) {') p.genln(';\nfor (int $i = $tmp; $i < $range_end; $i++) {')
if val == '_' { return } if val == '_' {
return
}
p.genln('$var_type $val = $i;') p.genln('$var_type $val = $i;')
} }
@ -404,13 +402,17 @@ fn (p mut Parser) gen_for_map_header(i, tmp, var_typ, val, typ string) {
p.genln('string $i = ((string*)keys_$tmp .data)[l];') p.genln('string $i = ((string*)keys_$tmp .data)[l];')
// TODO don't call map_get() for each key, fetch values while traversing // TODO don't call map_get() for each key, fetch values while traversing
// the tree (replace `map_keys()` above with `map_key_vals()`) // the tree (replace `map_keys()` above with `map_key_vals()`)
if val == '_' { return } if val == '_' {
return
}
p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);') p.genln('$var_typ $val = $def; map_get($tmp, $i, & $val);')
} }
fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) { fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) {
p.genln('for (int $i = 0; $i < ${varg}->len; $i++) {') p.genln('for (int $i = 0; $i < ${varg}->len; $i++) {')
if val == '_' { return } if val == '_' {
return
}
p.genln('$var_typ $val = (($var_typ *) $varg->args)[$i];') p.genln('$var_typ $val = (($var_typ *) $varg->args)[$i];')
} }
@ -421,13 +423,13 @@ fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_e
} }
if nr_elems == 0 { if nr_elems == 0 {
p.gen(' TCCSKIP(0) })') p.gen(' TCCSKIP(0) })')
} else { }
else {
p.gen(' })') p.gen(' })')
} }
// Need to do this in the second pass, otherwise it goes to the very top of the out.c file // Need to do this in the second pass, otherwise it goes to the very top of the out.c file
if !p.first_pass() { if !p.first_pass() {
p.cgen.set_placeholder(new_arr_ph, p.cgen.set_placeholder(new_arr_ph, '${new_arr}($nr_elems, $nr_elems, sizeof($typ), EMPTY_ARRAY_OF_ELEMS( $typ, $nr_elems ) { ')
'${new_arr}($nr_elems, $nr_elems, sizeof($typ), EMPTY_ARRAY_OF_ELEMS( $typ, $nr_elems ) { ')
} }
} }
@ -441,7 +443,8 @@ fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_po
if is_map { if is_map {
if is_ptr { if is_ptr {
func = 'map_set(' func = 'map_set('
} else { }
else {
func = 'map_set(&' func = 'map_set(&'
} }
// CAO on map is a bit more complicated as it loads // CAO on map is a bit more complicated as it loads
@ -468,7 +471,6 @@ fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_po
p.gen(', & ($typ []) { $val })') p.gen(', & ($typ []) { $val })')
} }
// returns true in case of an early return // returns true in case of an early return
fn (p mut Parser) gen_struct_init(typ string, t Type) bool { fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
// TODO hack. If it's a C type, we may need to add "struct" before declaration: // TODO hack. If it's a C type, we may need to add "struct" before declaration:
@ -511,6 +513,7 @@ fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
p.check(.rcbr) p.check(.rcbr)
return true return true
*/ */
} }
p.gen('($t.name*)memdup(&($t.name) {') p.gen('($t.name*)memdup(&($t.name) {')
} }
@ -527,7 +530,9 @@ fn (p mut Parser) gen_empty_map(typ string) {
fn (p mut Parser) cast(typ string) { fn (p mut Parser) cast(typ string) {
p.gen('(') p.gen('(')
defer { p.gen(')') } defer {
p.gen(')')
}
p.next() p.next()
pos := p.cgen.add_placeholder() pos := p.cgen.add_placeholder()
if p.tok == .rpar { if p.tok == .rpar {
@ -543,8 +548,7 @@ fn (p mut Parser) cast(typ string) {
p.warn('casting `$typ` to `$expr_typ` is not needed') p.warn('casting `$typ` to `$expr_typ` is not needed')
} }
// `face := FT_Face(cobj)` => `FT_Face face = *((FT_Face*)cobj);` // `face := FT_Face(cobj)` => `FT_Face face = *((FT_Face*)cobj);`
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' && casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' && typ != 'byteptr' && !typ.ends_with('*')
typ != 'byteptr' && !typ.ends_with('*')
p.expected_type = '' p.expected_type = ''
// `string(buffer)` => `tos2(buffer)` // `string(buffer)` => `tos2(buffer)`
// `string(buffer, len)` => `tos(buffer, len)` // `string(buffer, len)` => `tos(buffer, len)`
@ -561,7 +565,8 @@ fn (p mut Parser) cast(typ string) {
} }
p.gen(', ') p.gen(', ')
p.check_types(p.expression(), 'int') p.check_types(p.expression(), 'int')
} else { }
else {
if is_bytearr { if is_bytearr {
p.gen('.data') p.gen('.data')
} }
@ -618,26 +623,54 @@ fn type_default(typ string) string {
} }
// Default values for other types are not needed because of mandatory initialization // Default values for other types are not needed because of mandatory initialization
match typ { match typ {
'bool'{ return '0'} 'bool' {
'string'{ return 'tos3("")'} return '0'
'i8'{ return '0'}
'i16'{ return '0'}
'i64'{ return '0'}
'u16'{ return '0'}
'u32'{ return '0'}
'u64'{ return '0'}
'byte'{ return '0'}
'int'{ return '0'}
'rune'{ return '0'}
'f32'{ return '0.0'}
'f64'{ return '0.0'}
'byteptr'{ return '0'}
'voidptr'{ return '0'}
else {}
} }
'string' {
return 'tos3("")'
}
'i8' {
return '0'
}
'i16' {
return '0'
}
'i64' {
return '0'
}
'u16' {
return '0'
}
'u32' {
return '0'
}
'u64' {
return '0'
}
'byte' {
return '0'
}
'int' {
return '0'
}
'rune' {
return '0'
}
'f32' {
return '0.0'
}
'f64' {
return '0.0'
}
'byteptr' {
return '0'
}
'voidptr' {
return '0'
}
else {
}}
return '{0}' return '{0}'
// TODO this results in // TODO this results in
// error: expected a field designator, such as '.field = 4' // error: expected a field designator, such as '.field = 4'
// - Empty ee= (Empty) { . = {0} } ; // - Empty ee= (Empty) { . = {0} } ;
@ -661,6 +694,7 @@ else {}
else { '{0} '} else { '{0} '}
} }
*/ */
} }
fn (p mut Parser) gen_array_push(ph int, typ, expr_type, tmp, elm_type string) { fn (p mut Parser) gen_array_push(ph int, typ, expr_type, tmp, elm_type string) {
@ -669,7 +703,8 @@ fn (p mut Parser) gen_array_push(ph int, typ, expr_type, tmp, elm_type string) {
if push_array { if push_array {
p.cgen.set_placeholder(ph, '_PUSH_MANY(&') p.cgen.set_placeholder(ph, '_PUSH_MANY(&')
p.gen('), $tmp, $typ)') p.gen('), $tmp, $typ)')
} else { }
else {
p.check_types(expr_type, elm_type) p.check_types(expr_type, elm_type)
// Pass tmp var info to the _PUSH macro // Pass tmp var info to the _PUSH macro
// Prepend tmp initialisation and push call // Prepend tmp initialisation and push call

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module compiler module compiler
import ( import (
@ -40,7 +39,10 @@ fn (p mut Parser) get_type2() Type{
} }
// fn type // fn type
if p.tok == .key_fn { if p.tok == .key_fn {
mut f := Fn{name: '_', mod: p.mod} mut f := Fn{
name: '_'
mod: p.mod
}
p.next() p.next()
line_nr := p.scanner.line_nr line_nr := p.scanner.line_nr
p.fn_args(mut f) p.fn_args(mut f)
@ -60,6 +62,7 @@ fn (p mut Parser) get_type2() Type{
// Register anon fn type // Register anon fn type
fn_typ := Type{ fn_typ := Type{
name: f.typ_str() // 'fn (int, int) string' name: f.typ_str() // 'fn (int, int) string'
mod: p.mod mod: p.mod
func: f func: f
cat: .func cat: .func
@ -79,8 +82,8 @@ fn (p mut Parser) get_type2() Type{
if p.tok == .number || (p.tok == .name && !p.inside_const) { if p.tok == .number || (p.tok == .name && !p.inside_const) {
if p.tok == .name { if p.tok == .name {
typ += '[${p.mod}__$p.lit]' typ += '[${p.mod}__$p.lit]'
}
} else { else {
typ += '[$p.lit]' typ += '[$p.lit]'
} }
p.next() p.next()
@ -102,7 +105,9 @@ fn (p mut Parser) get_type2() Type{
val_type := p.get_type() // p.check_name() val_type := p.get_type() // p.check_name()
typ = 'map_$val_type' typ = 'map_$val_type'
p.register_map(typ) p.register_map(typ)
return Type{name: typ} return Type{
name: typ
}
} }
// ptr/ref // ptr/ref
mut warn := false mut warn := false
@ -123,7 +128,8 @@ fn (p mut Parser) get_type2() Type{
ti := p.cur_fn.dispatch_of.inst ti := p.cur_fn.dispatch_of.inst
if p.lit in ti.keys() { if p.lit in ti.keys() {
typ += ti[p.lit] typ += ti[p.lit]
} else { }
else {
typ += p.lit typ += p.lit
} }
// C.Struct import // C.Struct import
@ -153,8 +159,7 @@ fn (p mut Parser) get_type2() Type{
// "typ" not found? try "mod__typ" // "typ" not found? try "mod__typ"
if t.name == '' && !p.builtin_mod { if t.name == '' && !p.builtin_mod {
// && !p.first_pass() { // && !p.first_pass() {
if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') && if !typ.contains('array_') && p.mod != 'main' && !typ.contains('__') && !typ.starts_with('[') {
!typ.starts_with('[') {
typ = p.prepend_mod(typ) typ = p.prepend_mod(typ)
} }
t = p.table.find_type(typ) t = p.table.find_type(typ)
@ -195,7 +200,6 @@ fn (p mut Parser) get_type2() Type{
typ = 'Option_$typ' typ = 'Option_$typ'
p.table.register_type_with_parent(typ, 'Option') p.table.register_type_with_parent(typ, 'Option')
} }
// Because the code uses * to see if it's a pointer // Because the code uses * to see if it's a pointer
if typ == 'byteptr' { if typ == 'byteptr' {
typ = 'byte*' typ = 'byte*'
@ -212,6 +216,10 @@ fn (p mut Parser) get_type2() Type{
p.error('2 __ in gettype(): typ="$typ"') p.error('2 __ in gettype(): typ="$typ"')
} }
*/ */
return Type{name: typ, cat: cat}
return Type{
name: typ
cat: cat
}
} }

View File

@ -250,9 +250,9 @@ fn (p &Parser) gen_fmt() {
if s == '' { if s == '' {
return return
} }
files := ['cgen.v', 'comptime.v', 'cc.v', 'if_match.v'] files := ['get_type.v']
//if !p.file_path.contains('table.v') {return} if !p.file_path.contains('vlib/builtin') {return}
if !(p.file_name in files) { return } //if !(p.file_name in files) { return }
path := os.tmpdir() + '/' + p.file_name path := os.tmpdir() + '/' + p.file_name
println('generating ${path}') println('generating ${path}')
mut out := os.create(path) or { mut out := os.create(path) or {