1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

run vfmt on vlib/builtin

This commit is contained in:
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.
// []int == []int (also for: i64, f32, f64, byte, string)
fn array_eq<T>(a1, a2 []T) bool {
if a1.len != a2.len {
return false
}

View File

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

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
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 {
skipframes := xskipframes + 2
$if macos { return print_backtrace_skipping_top_frames_mac(skipframes) }
$if linux { return print_backtrace_skipping_top_frames_linux(skipframes) }
$if freebsd { return print_backtrace_skipping_top_frames_freebsd(skipframes) }
$if macos {
return print_backtrace_skipping_top_frames_mac(skipframes)
}
$if linux {
return print_backtrace_skipping_top_frames_linux(skipframes)
}
$if freebsd {
return print_backtrace_skipping_top_frames_freebsd(skipframes)
}
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" .')
return false
}
$if !android { // backtrace is not available on Android.
$if !android {
// backtrace is not available on Android.
$if glibc {
buffer := [100]byteptr
nr_ptrs := C.backtrace(*voidptr(buffer), 100)
nr_actual_frames := nr_ptrs - skipframes
mut sframes := []string
csymbols := C.backtrace_symbols(*voidptr(&buffer[skipframes]),
nr_actual_frames)
for i in 0..nr_actual_frames { sframes << tos2(csymbols[i]) }
csymbols := C.backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
for i in 0 .. nr_actual_frames {
sframes << tos2(csymbols[i])
}
for sframe in sframes {
executable := sframe.all_before('(')
addr := sframe.all_after('[').all_before(']')
beforeaddr := sframe.all_before('[')
cmd := 'addr2line -e $executable $addr'
// taken from os, to avoid depending on the os module inside builtin.v
f := C.popen(cmd.str, 'r')
if isnil(f) {
println(sframe) continue
println(sframe)
continue
}
buf := [1000]byte
mut output := ''
@ -78,9 +85,12 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
}
output = output.trim_space() + ':'
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')
}
// 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
}

View File

@ -1,166 +1,403 @@
module builtin
// <string.h>
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.realloc(a byteptr, b int) byteptr
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
fn C.popen(c byteptr, t byteptr) voidptr
// <execinfo.h>
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>
fn proc_pidpath(int, voidptr, int) int
fn C.realpath(byteptr, byteptr) &char
fn C.chmod(byteptr, int) int
fn C.printf(byteptr, ...byteptr) int
fn C.fputs(byteptr) int
fn C.fflush(byteptr) int
// TODO define args in these functions
fn C.fseek() int
fn C.fopen() voidptr
fn C.fwrite() int
fn C.fclose() int
fn C.pclose() int
fn C.system() int
fn C.setenv() int
fn C.unsetenv() int
fn C.access() int
fn C.remove() int
fn C.rmdir() int
fn C.chdir() int
fn C.fread() int
fn C.rewind() int
fn C.stat() int
fn C.lstat() int
fn C.rename() int
fn C.fgets() int
fn C.memset() int
fn C.sigemptyset() int
fn C.getcwd() int
fn C.signal() int
fn C.mktime() int
fn C.gettimeofday() int
fn C.sleep() int
fn C.usleep() int
fn C.opendir() voidptr
fn C.closedir() int
fn C.mkdir() int
fn C.srand() int
fn C.atof() int
fn C.tolower() int
fn C.toupper() int
fn C.getchar() int
fn C.strerror() charptr
fn C.snprintf() int
fn C.fprintf(byteptr, ...byteptr)
fn C.WIFEXITED() bool
fn C.WEXITSTATUS() int
fn C.WIFSIGNALED() bool
fn C.WTERMSIG() int
fn C.DEFAULT_LE() bool
fn C.DEFAULT_EQ() bool
fn C.DEFAULT_GT() bool
fn C.DEFAULT_EQUAL() bool
fn C.DEFAULT_NOT_EQUAL() bool
fn C.DEFAULT_LT() bool
fn C.DEFAULT_GE() bool
fn C.isatty() int
fn C.syscall() int
fn C.sysctl() int
// Windows
fn C._setmode(int, int) int
fn C._fileno(int) int
fn C._get_osfhandle(fd int) C.intptr_t
fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
fn C.SetHandleInformation(hObject voidptr, dwMask u32, dwFlags u32) bool
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.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumberOfBytesRead voidptr, lpOverlapped voidptr) bool
fn C.GetFileAttributesW(lpFileName byteptr) u32
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.RegCloseKey()
fn C.RegQueryValueEx() voidptr
fn C.RemoveDirectory() int
fn C.GetStdHandle() voidptr
fn C.SetConsoleMode()
fn C.GetConsoleMode() int
fn C._putws()
fn C.wprintf()
fn C.setbuf()
fn C.SymCleanup()
fn C.MultiByteToWideChar() int
fn C.wcslen() int
fn C.WideCharToMultiByte() int
fn C._wstat()
fn C._wrename()
fn C._wfopen() voidptr
fn C._wpopen() voidptr
fn C._pclose() int
fn C._wsystem() int
fn C._wgetenv() voidptr
fn C._putenv() int
fn C._waccess() int
fn C._wremove()
fn C.ReadConsole()
fn C.fgetws() voidptr
fn C.GetModuleFileName() int
fn C._wchdir()
fn C._wgetcwd() int
fn C._fullpath() int
fn C.GetCommandLine() voidptr
fn C.CommandLineToArgvW() &voidptr
fn C.LocalFree()
fn C.FindFirstFileW() voidptr
fn C.FindFirstFile() voidptr
fn C.FindNextFile() voidptr
fn C.FindClose()
fn C.MAKELANGID() int
fn C.FormatMessage() voidptr
fn C.CloseHandle()
fn C.GetExitCodeProcess()
fn C.RegOpenKeyEx() voidptr
fn C.GetTickCount() i64
fn C.Sleep()
fn C.WSAStartup(u16, &voidptr) int
fn C.WSAGetLastError() int
fn C.closesocket(int) int
fn C.vschannel_init(&C.TlsContext)
fn C.request(&C.TlsContext, int, &u16, byteptr, &byteptr)
fn C.vschannel_cleanup(&C.TlsContext)
fn C.URLDownloadToFile(int, &u16, &u16, int, int)
fn C.GetLastError() u32
fn C.CreateDirectory(byteptr, int) bool
fn C.BCryptGenRandom(int, voidptr, int, int) int
fn C.CreateMutex(int, bool, byteptr) voidptr
fn C.WaitForSingleObject(voidptr, int) int
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 {
return C.DEFAULT_GE(a, b)
}

View File

@ -1,9 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
/*
This is work in progress.
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.
*/
struct hashmap {
cap int
keys []string
@ -60,9 +59,12 @@ fn (m mut hashmap) set(key string, val int) {
for e.next != 0 {
e = e.next
}
e.next = &hashmapentry{key, val, 0}
} else {
m.table[idx] = hashmapentry{key, val, 0}
e.next = &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()))
idx := hash % m.cap
mut e := &m.table[idx]
for e.next != 0 { // todo unsafe {
for e.next != 0 {
// todo unsafe {
if e.key == key {
return e.val
}
@ -79,4 +82,8 @@ fn (m mut hashmap) get(key string) int {
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.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
pub fn ptr_str(ptr voidptr) string {
@ -42,9 +41,17 @@ pub fn (nn int) str() string {
return tos(buf + max - len, len)
}
pub fn (n i8) 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 (n i8) 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 {
mut n := nn
@ -84,6 +91,7 @@ pub fn (nn byte) str() string {
}
*/
pub fn (nn i64) str() string {
mut n := nn
if n == i64(0) {
@ -138,22 +146,14 @@ pub fn (b bool) str() string {
}
pub fn (n int) hex() string {
len := if n >= 0 {
n.str().len + 3
} else {
11
}
len := if n >= 0 { n.str().len + 3 } else { 11 }
hex := malloc(len) // 0x + \n
count := int(C.sprintf(charptr(hex), '0x%x', n))
return tos(hex, count)
}
pub fn (n i64) hex() string {
len := if n >= i64(0) {
n.str().len + 3
} else {
19
}
len := if n >= i64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len)
count := int(C.sprintf(charptr(hex), '0x%'C.PRIx64, n))
return tos(hex, count)

View File

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

View File

@ -1,9 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
/*
struct Option2<T> {
data T
@ -14,6 +12,7 @@ struct Option2<T> {
}
*/
struct Option {
data [300]byte
error string
@ -36,7 +35,9 @@ fn opt_ok(data voidptr, size int) Option {
// used internally when returning `none`
fn opt_none() Option {
return Option{ is_none: true }
return Option{
is_none: true
}
}
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.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
import strconv
/*
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
@ -134,7 +132,9 @@ pub fn cstring_to_vstring(cstr byteptr) 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)
}
@ -199,7 +199,6 @@ fn (a mut []RepIndex) sort() {
a.sort_with_compare(compare_rep_index)
}
// TODO
/*
fn (a RepIndex) < (b RepIndex) bool {
@ -207,6 +206,7 @@ fn (a RepIndex) < (b RepIndex) bool {
}
*/
fn compare_rep_index(a, b &RepIndex) int {
if a.idx < b.idx {
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,
// and which rep/with pair it refers to.
idxs << RepIndex{idx, rep_i}
idxs << RepIndex{
idx,rep_i}
idx++
new_len += with.len - rep.len
}
@ -317,7 +318,8 @@ pub fn (s string) u64() u64 {
// ==
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')
}
if s.len != a.len {
@ -412,7 +414,9 @@ pub fn (s string) split_nth(delim string, nth int) []string {
j++
}
was_last := nth > 0 && res.len == nth
if was_last{break}
if was_last {
break
}
last := i == s.len - 1
if is_delim || last {
if !is_delim && last {
@ -460,6 +464,7 @@ fn (s string) left(n int) string {
}
return s.substr(0, n)
}
// 'hello'.right(2) => 'llo'
fn (s string) right(n int) string {
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)')
}
len := end - start
mut res := string{
len: len
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[len] = `\0`
/*
res := string {
str: s.str + start
len: len
}
*/
return res
}
@ -565,10 +569,11 @@ fn (s string) index_kmp(p string) int {
return -1
}
pub fn (s string) index_any(chars string) int {
for c in chars {
index := s.index(c.str()) or { continue }
index := s.index(c.str()) or {
continue
}
return index
}
return -1
@ -666,7 +671,9 @@ pub fn (s string) contains(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
}
@ -706,22 +713,24 @@ pub fn (s string) capitalize() string {
pub fn (s string) title() string {
words := s.split(' ')
mut tit := []string
for word in words {
tit << word.capitalize()
}
title := tit.join(' ')
return title
}
// 'hey [man] how you doin'
// find_between('[', ']') == 'man'
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'
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)
}
@ -756,6 +765,7 @@ pub fn (a []string) to_c() voidptr {
}
*/
pub fn (c byte) is_space() bool {
return c in [` `, `\n`, `\t`, `\v`, `\f`, `\r`]
}
@ -859,6 +869,7 @@ pub fn (s string) ustring() ustring {
s: s
// runes will have at least s.len elements, save reallocations
// TODO use VLA for small strings?
runes: new_array(0, s.len, sizeof(int))
}
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
// right away. Uses global buffer for storing runes []int array.
__global g_ustring_runes []int
pub fn (s string) ustring_tmp() ustring {
if g_ustring_runes.len == 0 {
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 {
panic('substr($_start, $_end) out of bounds (len=$u.len)')
}
end := if _end >= u.len {
u.s.len
}
else {
u.runes[_end]
}
end := if _end >= u.len { u.s.len } else { u.runes[_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'
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)
}
@ -1158,7 +1167,6 @@ pub fn (c byte) is_white() bool {
return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r`
}
pub fn (s string) hash() int {
// mut h := s.hash_cache
mut h := 0
@ -1193,3 +1201,4 @@ pub fn (s string) repeat(count int) string {
ret[s.len * count] = 0
return string(ret)
}

View File

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

View File

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

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module compiler
import strings
@ -9,14 +8,15 @@ import strings
const (
dot_ptr = '->'
)
// returns the type of the new variable
fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
p.is_var_decl = true
mut typ := p.bool_expression()
// mut typ, expr := p.tmp_expr()
p.is_var_decl = false
if typ.starts_with('...') { typ = typ[3..] }
if typ.starts_with('...') {
typ = typ[3..]
}
// p.gen('/*after expr*/')
// Option check ? or {
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;`
if !p.is_empty_c_struct_init && !typ.starts_with('[') {
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]!!`
// ... should translate to the following in C `f32 v[2] = {1.1, 2.2};`
initializer := p.cgen.cur_line
if initializer.len > 0 {
p.cgen.resetln(' = {' + initializer.all_after('{'))
} else if initializer.len == 0 {
}
else if initializer.len == 0 {
p.cgen.resetln(' = { 0 }')
}
}
if is_static {
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) {
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 {
''
}
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 { '' }
fn_name_cgen := p.table.fn_gen_name(f)
// str_args := f.str_args(p.table)
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
if p.tok == .key_orelse {
p.gen_handle_option_or_else(typ, '', pos)
} else {
}
else {
if is_fn_call {
p.gen(';')
} else {
}
else {
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_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('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
// when p.cgen.line_directives is true an extra
// line is added so we need to account for that
expr_line := if p.cgen.line_directives {
p.cgen.lines[p.cgen.lines.len-3]
} else {
p.cgen.lines[p.cgen.lines.len-2]
}
expr_line := if p.cgen.line_directives { p.cgen.lines[p.cgen.lines.len - 3] } else { p.cgen.lines[p.cgen.lines.len - 2] }
last_expr := expr_line[last_ph..]
p.cgen.lines[p.cgen.lines.len - 2] = ''
// 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('$name = $last_expr')
p.genln('}')
} else if is_assign {
}
else if is_assign {
p.genln('$name = *($typ*)${tmp}.data;')
}
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 {
sb.write('\t')
sb.writeln(table.cgen_name_type_pair(field.name,
field.typ) + ';')
sb.writeln(table.cgen_name_type_pair(field.name, field.typ) + ';')
}
sb.writeln('};\n')
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 {
index_expr = 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..]
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 {
p.gen('$tmp')
def := type_default(typ)
p.cgen.insert_before('$typ $tmp = $def; ' +
'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
p.cgen.insert_before('$typ $tmp = $def; ' + 'bool $tmp_ok = map_get(/*$p.file_name : $p.scanner.line_nr*/$index_expr, & $tmp);')
}
else if cfg.is_arr {
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 {
p.gen('string_substr2($index_expr)')
} else {
}
else {
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_ok) $tmp = tos((byte *)"", 0);')
}
}
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(' ', '')
if f.name.len == 1 {
match f.name[0] {
`+` { name = name.replace('+', 'op_plus') }
`-` { name = name.replace('-', 'op_minus') }
`*` { name = name.replace('*', 'op_mul') }
`/` { name = name.replace('/', 'op_div') }
`%` { name = name.replace('%', 'op_mod') }
else {}
`+` {
name = name.replace('+', 'op_plus')
}
`-` {
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 {
@ -288,20 +292,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
// Obfuscate but skip certain names
// TODO ugly, fix
// NB: the order here is from faster to potentially slower checks
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') {
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') {
mut idx := table.obf_ids[name]
// No such function yet, register it
if idx == 0 {
@ -316,9 +307,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
return name
}
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string,
cgen_name string, ftyp string, method_ph int)
{
fn (p mut Parser) gen_method_call(receiver &Var, receiver_type string, cgen_name string, ftyp string, method_ph int) {
// mut cgen_name := p.table.fn_gen_name(f)
mut method_call := cgen_name + ' ('
// 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
cast = receiver_type.all_after('array_')
cast = '*($cast*) '
} else {
}
else {
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) {
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];')
}
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++) {')
if val == '_' { return }
if val == '_' {
return
}
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
// p.genln('array_byte bytes_$tmp = string_bytes( $tmp );')
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 = ${tmp}.str[$i];')
}
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++) {')
if val == '_' { return }
if val == '_' {
return
}
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];')
// TODO don't call map_get() for each key, fetch values while traversing
// 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);')
}
fn (p mut Parser) gen_for_varg_header(i, varg, var_typ, val string) {
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];')
}
@ -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 {
p.gen(' TCCSKIP(0) })')
} else {
}
else {
p.gen(' })')
}
// Need to do this in the second pass, otherwise it goes to the very top of the out.c file
if !p.first_pass() {
p.cgen.set_placeholder(new_arr_ph,
'${new_arr}($nr_elems, $nr_elems, sizeof($typ), EMPTY_ARRAY_OF_ELEMS( $typ, $nr_elems ) { ')
p.cgen.set_placeholder(new_arr_ph, '${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_ptr {
func = 'map_set('
} else {
}
else {
func = 'map_set(&'
}
// 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 })')
}
// returns true in case of an early return
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:
@ -511,6 +513,7 @@ fn (p mut Parser) gen_struct_init(typ string, t Type) bool {
p.check(.rcbr)
return true
*/
}
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) {
p.gen('(')
defer { p.gen(')') }
defer {
p.gen(')')
}
p.next()
pos := p.cgen.add_placeholder()
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')
}
// `face := FT_Face(cobj)` => `FT_Face face = *((FT_Face*)cobj);`
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' &&
typ != 'byteptr' && !typ.ends_with('*')
casting_voidptr_to_value := expr_typ == 'void*' && typ != 'int' && typ != 'byteptr' && !typ.ends_with('*')
p.expected_type = ''
// `string(buffer)` => `tos2(buffer)`
// `string(buffer, len)` => `tos(buffer, len)`
@ -561,7 +565,8 @@ fn (p mut Parser) cast(typ string) {
}
p.gen(', ')
p.check_types(p.expression(), 'int')
} else {
}
else {
if is_bytearr {
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
match typ {
'bool'{ return '0'}
'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 {}
'bool' {
return '0'
}
'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}'
// TODO this results in
// error: expected a field designator, such as '.field = 4'
// - Empty ee= (Empty) { . = {0} } ;
@ -661,6 +694,7 @@ else {}
else { '{0} '}
}
*/
}
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 {
p.cgen.set_placeholder(ph, '_PUSH_MANY(&')
p.gen('), $tmp, $typ)')
} else {
}
else {
p.check_types(expr_type, elm_type)
// Pass tmp var info to the _PUSH macro
// Prepend tmp initialisation and push call

View File

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