Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,645 @@
|
||||
module builtin
|
||||
|
||||
import strings
|
||||
/// Internal representation of `array` type. It is used to implement slices and to make slices behave correctly
|
||||
/// it simply stores reference to original array and to index them properly it does index array relative to `index_start`.
|
||||
|
||||
struct array_buffer {
|
||||
arr JS.Array
|
||||
index_start int
|
||||
len int
|
||||
cap int
|
||||
has_slice bool
|
||||
}
|
||||
|
||||
fn (mut a array_buffer) make_copy() {
|
||||
if a.index_start != 0 || a.has_slice {
|
||||
mut new_arr := JS.makeEmptyJSArray()
|
||||
for i in 0 .. a.len {
|
||||
#new_arr.push(a.val.get(i))
|
||||
|
||||
mut x := i
|
||||
x = x
|
||||
}
|
||||
new_arr = new_arr
|
||||
#a.val.arr = new_arr
|
||||
#a.val.index_start = new int(0)
|
||||
#a.val.has_slice = new bool(false)
|
||||
}
|
||||
}
|
||||
|
||||
#array_buffer.prototype.make_copy = function() { return array_buffer_make_copy(this) }
|
||||
// TODO(playX): Should this be implemented fully in JS, use generics or just voidptr?
|
||||
fn (a array_buffer) get(ix int) voidptr {
|
||||
mut res := unsafe { nil }
|
||||
#res = a.arr[a.index_start.val + ix.val];
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn (mut a array_buffer) set(ix int, val voidptr) {
|
||||
#a.val.arr[a.val.index_start.valueOf() + ix.valueOf()] = val;
|
||||
}
|
||||
|
||||
#array_buffer.prototype.get = function(ix) { return array_buffer_get(this,ix);}
|
||||
#array_buffer.prototype.set = function(ix,val) { array_buffer_set(this,ix,val); }
|
||||
|
||||
struct array {
|
||||
pub mut:
|
||||
arr array_buffer
|
||||
|
||||
len int
|
||||
cap int
|
||||
}
|
||||
|
||||
fn v_sort(mut arr array, comparator fn (voidptr, voidptr) int) {
|
||||
mut need_iter := true
|
||||
for need_iter {
|
||||
need_iter = false
|
||||
for i := 1; i < arr.len; i++ {
|
||||
if comparator(arr[i], arr[i - 1]) != 1 {
|
||||
tmp := arr[i]
|
||||
arr[i] = arr[i - 1]
|
||||
arr[i - 1] = tmp
|
||||
need_iter = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trim trims the array length to "index" without modifying the allocated data. If "index" is greater than len nothing will be changed.
|
||||
pub fn (mut a array) trim(index int) {
|
||||
if index < a.len {
|
||||
a.len = index
|
||||
}
|
||||
}
|
||||
|
||||
#function flatIntoArray(target, source, sourceLength, targetIndex, depth) {
|
||||
#"use strict";
|
||||
#
|
||||
#for (var sourceIndex = 0; sourceIndex < sourceLength; ++sourceIndex) {
|
||||
#if (sourceIndex in source) {
|
||||
#var element = source[sourceIndex];
|
||||
#if (depth > 0 && Array.isArray(element))
|
||||
#targetIndex = flatIntoArray(target, element, element.length, targetIndex, depth - 1);
|
||||
#else {
|
||||
#target[targetIndex] = element;
|
||||
#++targetIndex;
|
||||
#}
|
||||
#}
|
||||
#}
|
||||
#return targetIndex;
|
||||
#}
|
||||
#function flatArray(target,depth) {
|
||||
#var array = target
|
||||
#var length = array.length;
|
||||
#var depthNum = 1;
|
||||
#
|
||||
#if (depth !== undefined)
|
||||
#depthNum = +depth
|
||||
#
|
||||
#var result = []
|
||||
#
|
||||
#flatIntoArray(result, array, length, 0, depthNum);
|
||||
#return result;
|
||||
#}
|
||||
|
||||
@[unsafe]
|
||||
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
if count < 0 {
|
||||
panic('array.repeat: count is negative: ${count}')
|
||||
}
|
||||
mut arr := empty_array()
|
||||
|
||||
if a.len > 0 {
|
||||
for _ in 0 .. count {
|
||||
for i in 0 .. a.len {
|
||||
if depth > 0 {
|
||||
// TODO
|
||||
} else {
|
||||
arr.push(a.arr.get(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// last returns the last element of the array.
|
||||
pub fn (a array) last() voidptr {
|
||||
mut res := unsafe { nil }
|
||||
#res = a.arr.get(new int(a.len-1));
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn (a array) get(ix int) voidptr {
|
||||
if ix < 0 || ix >= a.len {
|
||||
return unsafe { nil }
|
||||
}
|
||||
mut result := unsafe { nil }
|
||||
#result = a.arr.get(ix)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
pub fn (a array) repeat(count int) array {
|
||||
unsafe {
|
||||
return a.repeat_to_depth(count, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#function makeEmptyArray() { return new array(new array_buffer({ arr: [], len: new int(0), index_start: new int(0), cap: new int(0) })); }
|
||||
#function makeEmptyJSArray() { return new Array(); }
|
||||
|
||||
fn JS.makeEmptyArray() array
|
||||
fn JS.makeEmptyJSArray() JS.Array
|
||||
fn empty_array() array {
|
||||
return JS.makeEmptyArray()
|
||||
}
|
||||
|
||||
#function v_clone_for_array_value(value) {
|
||||
#if (value instanceof $ref || value instanceof voidptr || typeof value === 'function') return value;
|
||||
#return v_clone_value(value);
|
||||
#}
|
||||
|
||||
fn (a &array) set_len(i int) {
|
||||
#a.arr.arr.length=i
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
||||
#v_sort(a, compare instanceof voidptr ? compare.val : compare)
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort_with_compare_old(compare voidptr) {
|
||||
#a.val.arr.arr.sort(compare instanceof voidptr ? compare.val : compare)
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort() {
|
||||
#a.val.arr.arr.sort($sortComparator)
|
||||
}
|
||||
|
||||
pub fn (a array) index(v string) int {
|
||||
for i in 0 .. a.len {
|
||||
#if (a.arr.get(i).toString() == v.toString())
|
||||
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
pub fn (a array) last_index(v string) int {
|
||||
for i := a.len - 1; i >= 0; i-- {
|
||||
#if (a.arr.get(i).toString() == v.toString())
|
||||
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
pub fn (a array) slice(start int, end int) array {
|
||||
mut result := a
|
||||
#let slice = a.arr.arr.slice(start,end)
|
||||
#result = new array(new array_buffer({arr: a.arr.arr, len: new int(slice.length),cap: new int(slice.length),index_start: new int(start),has_slice: new bool(true)}))
|
||||
#a.arr.has_slice = true
|
||||
//#v_makeSlice(result)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
pub fn (mut a array) insert(i int, val voidptr) {
|
||||
#a.val.arr.make_copy()
|
||||
#a.val.arr.arr.splice(i,0,v_clone_for_array_value(val))
|
||||
#a.val.arr.len.val = a.val.arr.arr.length
|
||||
}
|
||||
|
||||
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||
#a.val.arr.make_copy()
|
||||
#a.val.arr.arr.splice(i,0,...val.arr.slice(0,+size).map(v_clone_for_array_value))
|
||||
#a.val.arr.len.val = a.val.arr.arr.length
|
||||
}
|
||||
|
||||
fn (mut a array) push(val voidptr) {
|
||||
#a.val.arr.make_copy()
|
||||
#if (arguments[2] && arguments[2].valueOf()) {a.val.arr.arr.push(...val.map(v_clone_for_array_value))} else {
|
||||
#a.val.arr.arr.push(v_clone_for_array_value(val))
|
||||
#}
|
||||
#a.val.arr.len.val = a.val.arr.arr.length
|
||||
}
|
||||
|
||||
fn v_filter(arr array, callback fn (voidptr) bool) array {
|
||||
mut filtered := empty_array()
|
||||
|
||||
for i := 0; i < arr.arr.len; i++ {
|
||||
if callback(arr.arr.get(i)) {
|
||||
filtered.push(arr.arr.get(i))
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
fn v_map(arr array, callback fn (voidptr) voidptr) array {
|
||||
mut mapped := empty_array()
|
||||
|
||||
for i := 0; i < arr.arr.len; i++ {
|
||||
mapped.push(callback(arr.arr.get(i)))
|
||||
}
|
||||
|
||||
return mapped
|
||||
}
|
||||
|
||||
struct array_iterator {
|
||||
ix int
|
||||
end int
|
||||
arr JS.Array
|
||||
}
|
||||
|
||||
#array_iterator.prototype.next = function () {
|
||||
#if (this.ix.val < this.end.val) {
|
||||
#this.ix.val++;
|
||||
#return {done: false, value: this.arr.arr.get(new int(this.ix.val-1))}
|
||||
#} else {
|
||||
#return {done: true, value: undefined}
|
||||
#}
|
||||
#}
|
||||
#array_iterator.prototype[Symbol.iterator] = function () { return this; }
|
||||
|
||||
#array.prototype[Symbol.iterator] = function () { return new array_iterator({ix: new int(0),end: new int(this.arr.len),arr: this}); }
|
||||
#array.prototype.entries = function () { let result = []; for (let key = this.arr.index_start.val;key < this.arr.len.val;key++) { result.push([new int(key), this.arr.get(new int(key))]); } return result[Symbol.iterator](); }
|
||||
#array.prototype.map = function(callback) { return v_map(this,callback); }
|
||||
#array.prototype.filter = function(callback) { return v_filter(this,callback); }
|
||||
#Object.defineProperty(array.prototype,'cap',{ get: function () { return this.len; } })
|
||||
#array.prototype.any = function (value) {
|
||||
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
||||
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||
#if (val(this.arr.get(i)))
|
||||
#return true;
|
||||
#
|
||||
#return false;
|
||||
#}
|
||||
|
||||
#array.prototype.all = function (value) {
|
||||
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
||||
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||
#if (!val(this.arr.get(i)))
|
||||
#return false;
|
||||
#
|
||||
#return true;
|
||||
#}
|
||||
//#Object.defineProperty(array_buffer.prototype,"len", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = l.valueOf(); } })
|
||||
//#Object.defineProperty(array_buffer.prototype,"cap", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = l.valueOf(); } })
|
||||
#
|
||||
#
|
||||
#function v_makeSlice(array) { Object.defineProperty(array,'len', {get: function() { return this.arr.len; }, set: function(l) { this.arr.len = l; }}) }
|
||||
// delete deletes array element at index `i`.
|
||||
pub fn (mut a array) delete(i int) {
|
||||
a.delete_many(i, 1)
|
||||
}
|
||||
|
||||
fn arr_copy(mut dst array, src array, count int) {
|
||||
for i := 0; i < count; i++ {
|
||||
dst.arr.set(i, src.arr.get(i))
|
||||
}
|
||||
}
|
||||
|
||||
// delete_many deletes `size` elements beginning with index `i`.
|
||||
pub fn (mut a array) delete_many(i int, size int) {
|
||||
#a.val.arr.make_copy()
|
||||
#a.val.arr.arr.splice(i.valueOf(),size.valueOf())
|
||||
#a.val.arr.len.val = a.val.arr.arr.length
|
||||
}
|
||||
|
||||
// prepend prepends one value to the array.
|
||||
pub fn (mut a array) prepend(val voidptr) {
|
||||
a.insert(0, val)
|
||||
}
|
||||
|
||||
// prepend_many prepends another array to this array.
|
||||
@[unsafe]
|
||||
pub fn (mut a array) prepend_many(val voidptr, size int) {
|
||||
unsafe { a.insert_many(0, val, size) }
|
||||
}
|
||||
|
||||
pub fn (a array) reverse() array {
|
||||
mut res := empty_array()
|
||||
#res.arr.arr = Array.from(a.arr).reverse()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (mut a array) reverse_in_place() {
|
||||
#a.val.arr.arr.reverse()
|
||||
}
|
||||
|
||||
#array.prototype.$includes = function (elem) { return this.arr.arr.find(function(e) { return vEq(elem,e); }) !== undefined;}
|
||||
|
||||
pub fn (mut a array) clear() {
|
||||
#a.val.arr.make_copy()
|
||||
#a.val.arr.arr.length = 0
|
||||
#a.val.arr.len.val = 0
|
||||
}
|
||||
|
||||
// reduce executes a given reducer function on each element of the array, resulting in a single output value.
|
||||
pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
||||
mut accum_ := accum_start
|
||||
/*#for (let i = 0;i < a.arr.length;i++) {
|
||||
#accum_ = iter(accum_, a.arr[i])
|
||||
#}*/
|
||||
for i in 0 .. a.len {
|
||||
accum_ = iter(accum_, a.get(i))
|
||||
}
|
||||
|
||||
return accum_
|
||||
}
|
||||
|
||||
pub fn (mut a array) pop() voidptr {
|
||||
mut res := unsafe { nil }
|
||||
#a.val.arr.make_copy()
|
||||
#res = a.val.arr.arr.pop()
|
||||
#a.val.arr.len.val = a.val.arr.arr.length
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (a array) first() voidptr {
|
||||
mut res := unsafe { nil }
|
||||
#res = a.arr.get(new int(0))
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
#array.prototype.toString = function () {
|
||||
#let res = "["
|
||||
#for (let i = 0; i < this.arr.arr.length;i++) {
|
||||
#res += this.arr.get(i).toString();
|
||||
#if (i != this.arr.arr.length-1)
|
||||
#res += ', '
|
||||
#}
|
||||
#res += ']'
|
||||
#return res;
|
||||
#
|
||||
#}
|
||||
|
||||
pub fn (a array) contains(key voidptr) bool
|
||||
|
||||
// delete_last effectively removes last element of an array.
|
||||
pub fn (mut a array) delete_last() {
|
||||
#a.val.arr.arr.pop();
|
||||
}
|
||||
|
||||
@[unsafe]
|
||||
pub fn (a &array) free() {
|
||||
}
|
||||
|
||||
// todo: once (a []u8) will work rewrite this
|
||||
pub fn (a array) bytestr() string {
|
||||
res := ''
|
||||
#for (let i = 0;i < a.arr.len.valueOf();i++) res.str += String.fromCharCode(a.arr.get(new int(i)))
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (a []string) str() string {
|
||||
mut sb := strings.new_builder(a.len * 3)
|
||||
sb.write_string('[')
|
||||
for i in 0 .. a.len {
|
||||
val := a[i]
|
||||
sb.write_string("'")
|
||||
sb.write_string(val)
|
||||
sb.write_string("'")
|
||||
if i < a.len - 1 {
|
||||
sb.write_string(', ')
|
||||
}
|
||||
}
|
||||
sb.write_string(']')
|
||||
res := sb.str()
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (a array) to_js_array() JS.Array {
|
||||
tmp := JS.Array.prototype.constructor()
|
||||
for i in 0 .. a.len {
|
||||
tmp.push(a.arr.get(i))
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
pub fn (a array) to_number_array() JS.Array {
|
||||
tmp := JS.Array.prototype.constructor()
|
||||
for i in 0 .. a.len {
|
||||
elem := a.arr.get(i)
|
||||
_ := elem
|
||||
#tmp.push(Number(elem.valueOf()));
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// push_many - appends multiple values to the end of the array.
|
||||
pub fn (mut a array) push_many(val voidptr, size int) {
|
||||
a.insert_many(a.len, val, size)
|
||||
}
|
||||
|
||||
type EveryFn = fn (JS.Number, JS.Number) JS.Boolean
|
||||
|
||||
type BigEveryFn = fn (JS.BigInt, JS.Number) JS.Boolean
|
||||
|
||||
pub interface JS.TypedArray {
|
||||
mut:
|
||||
byteLength JS.Number
|
||||
byteOffset JS.Number
|
||||
length JS.Number
|
||||
}
|
||||
|
||||
pub interface JS.Uint8Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Uint16Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Uint32Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.BigUint64Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.BigInt
|
||||
every(JS.BigEveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Int8Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Int16Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Int32Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.BigInt64Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.BigInt
|
||||
every(JS.BigEveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Float32Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub interface JS.Float64Array {
|
||||
JS.TypedArray
|
||||
at(index JS.Number) JS.Number
|
||||
every(JS.EveryFn) JS.Boolean
|
||||
}
|
||||
|
||||
pub fn uint8_array(arr []u8) JS.Uint8Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut uint_arr := JS.Uint8Array{}
|
||||
#uint_arr = new Uint8Array(tmp)
|
||||
|
||||
return uint_arr
|
||||
}
|
||||
|
||||
pub fn uint16_array(arr []u16) JS.Uint16Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut uint_arr := JS.Uint16Array{}
|
||||
#uint_arr = new Uint16Array(tmp)
|
||||
|
||||
return uint_arr
|
||||
}
|
||||
|
||||
pub fn uint32_array(arr []u32) JS.Uint32Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut uint_arr := JS.Uint32Array{}
|
||||
#uint_arr = new Uint32Array(tmp)
|
||||
|
||||
return uint_arr
|
||||
}
|
||||
|
||||
pub fn int8_array(arr []i8) JS.Int8Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut int_arr := JS.Int8Array{}
|
||||
#int_arr = new Int8Array(tmp)
|
||||
|
||||
return int_arr
|
||||
}
|
||||
|
||||
pub fn int16_array(arr []i16) JS.Int16Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut int_arr := JS.Int16Array{}
|
||||
#int_arr = new Int16Array(tmp)
|
||||
|
||||
return int_arr
|
||||
}
|
||||
|
||||
pub fn int32_array(arr []int) JS.Int32Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut int_arr := JS.Int32Array{}
|
||||
#int_arr = new Int32Array(tmp)
|
||||
|
||||
return int_arr
|
||||
}
|
||||
|
||||
pub fn int64_array(arr []i64) JS.BigInt64Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut int_arr := JS.BigInt64Array{}
|
||||
#int_arr = new BigInt64Array(tmp)
|
||||
|
||||
return int_arr
|
||||
}
|
||||
|
||||
pub fn uint64_array(arr []u64) JS.BigUint64Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut int_arr := JS.BigUint64Array{}
|
||||
#int_arr = new BigUint64Array(tmp)
|
||||
|
||||
return int_arr
|
||||
}
|
||||
|
||||
pub fn float32_array(arr []f32) JS.Float32Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut float_arr := JS.Float32Array{}
|
||||
#float_arr = new Float32Array(tmp)
|
||||
|
||||
return float_arr
|
||||
}
|
||||
|
||||
pub fn float64_array(arr []f64) JS.Float64Array {
|
||||
#let tmp = new Array();
|
||||
|
||||
for elem in arr {
|
||||
_ := elem
|
||||
#tmp.push(elem.val)
|
||||
}
|
||||
mut float_arr := JS.Float64Array{}
|
||||
#float_arr = new Float64Array(tmp)
|
||||
|
||||
return float_arr
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,183 @@
|
||||
module builtin
|
||||
|
||||
// used to generate JS throw statements.
|
||||
|
||||
$if js_node {
|
||||
#var $fs = require('fs');
|
||||
}
|
||||
|
||||
@[noreturn]
|
||||
pub fn js_throw(s any) {
|
||||
#throw s
|
||||
|
||||
for {}
|
||||
}
|
||||
|
||||
#let globalPrint, globalWrite;
|
||||
$if js_freestanding {
|
||||
#globalPrint = globalThis.print
|
||||
#globalWrite = (typeof globalThis.write === 'function')? write: globalThis.print
|
||||
}
|
||||
|
||||
pub fn flush_stdout() {
|
||||
// needed for parity with builtin.c.v
|
||||
}
|
||||
|
||||
pub fn flush_stderr() {
|
||||
// needed for parity with builtin.c.v
|
||||
}
|
||||
|
||||
pub fn println(s string) {
|
||||
$if js_freestanding {
|
||||
#globalPrint(s.str)
|
||||
} $else {
|
||||
#console.log(s.str)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(s string) {
|
||||
$if js_node {
|
||||
#$process.stdout.write(s.str)
|
||||
} $else $if js_freestanding {
|
||||
#globalWrite(s.str)
|
||||
} $else {
|
||||
panic('Cannot `print` in a browser, use `println` instead')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eprintln(s string) {
|
||||
$if js_freestanding {
|
||||
#globalPrint(s.str)
|
||||
} $else {
|
||||
#console.error(s.str)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eprint(s string) {
|
||||
$if js_node {
|
||||
#$process.stderr.write(s.str)
|
||||
} $else {
|
||||
panic('Cannot `eprint` in a browser, use `println` instead')
|
||||
}
|
||||
}
|
||||
|
||||
// input_character gives back a single character, read from the standard input.
|
||||
// It returns -1 on error (when the input is finished (EOF), on a broken pipe etc).
|
||||
pub fn input_character() int {
|
||||
$if js_node {
|
||||
mut ch := -1
|
||||
#try {
|
||||
#const read_buffer = Buffer.alloc(1)
|
||||
#const nbytes = $fs.readSync(0, read_buffer, 0, 1, null)
|
||||
#if (nbytes > 0) { ch.val = read_buffer[0] }
|
||||
#} catch (e) {}
|
||||
|
||||
return ch
|
||||
} $else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// print_character writes the single character `ch` to the standard output.
|
||||
// It returns the written character value, or panics if the active JS runtime
|
||||
// does not support stdout writes.
|
||||
pub fn print_character(ch u8) int {
|
||||
print(ch.ascii_str())
|
||||
return ch
|
||||
}
|
||||
|
||||
// Exits the process in node, and halts execution in the browser
|
||||
// because `process.exit` is undefined. Workaround for not having
|
||||
// a 'real' way to exit in the browser.
|
||||
@[noreturn]
|
||||
pub fn exit(c int) {
|
||||
JS.process.exit(c)
|
||||
js_throw('exit(${c})')
|
||||
}
|
||||
|
||||
fn opt_ok(data voidptr, option Option) {
|
||||
#option.state = 0
|
||||
#option.err = none__
|
||||
#option.data = data
|
||||
}
|
||||
|
||||
pub fn unwrap(opt string) string {
|
||||
mut o := Option{}
|
||||
#o = opt
|
||||
if o.state != 0 {
|
||||
js_throw(o.err)
|
||||
}
|
||||
|
||||
mut res := ''
|
||||
#res = opt.data
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn js_stacktrace() string {
|
||||
stacktrace := ''
|
||||
#let err = new TypeError();
|
||||
#err.name = 'stacktrace: '
|
||||
#stacktrace.str = err.stack
|
||||
|
||||
return stacktrace
|
||||
}
|
||||
|
||||
// v_clone_value preserves standalone JS semantics for V clone methods.
|
||||
#function v_clone_value(value) {
|
||||
#if (value === null || value === undefined) return value;
|
||||
#if (value instanceof $ref) return new $ref(v_clone_value(value.val));
|
||||
#if (value instanceof array) return array_clone(value);
|
||||
#if (value instanceof map) {
|
||||
#let cloned = {}
|
||||
#for (const key in value.map) cloned[key] = { key: v_clone_value(value.map[key].key), val: v_clone_value(value.map[key].val) }
|
||||
#return new map(cloned);
|
||||
#}
|
||||
#if (typeof value !== 'object') return value;
|
||||
#if (typeof value.$toJS === 'function') {
|
||||
#let cloned = Object.create(Object.getPrototypeOf(value) || Object.prototype);
|
||||
#for (const key of Object.keys(value)) cloned[key] = v_clone_value(value[key]);
|
||||
#return cloned;
|
||||
#}
|
||||
#let cloned;
|
||||
#try {
|
||||
#cloned = typeof value.constructor === 'function' ? new value.constructor({}) : Object.create(Object.getPrototypeOf(value));
|
||||
#} catch (e) {
|
||||
#cloned = Object.create(Object.getPrototypeOf(value) || Object.prototype);
|
||||
#}
|
||||
#for (const key of Object.keys(value)) cloned[key] = v_clone_value(value[key]);
|
||||
#return cloned;
|
||||
#}
|
||||
|
||||
pub fn print_backtrace() {
|
||||
println(js_stacktrace())
|
||||
}
|
||||
|
||||
pub fn (a array) clone() array {
|
||||
mut res := empty_array()
|
||||
#const source = a instanceof $ref ? a.val : a
|
||||
#const cloned = source.arr.arr.slice(source.arr.index_start.valueOf(), source.arr.index_start.valueOf() + source.len.valueOf()).map(v_clone_value)
|
||||
#res = new array(new array_buffer({arr: cloned, len: new int(cloned.length), cap: new int(cloned.length), index_start: new int(0), has_slice: new bool(false)}))
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Check for nil value
|
||||
pub fn isnil(val voidptr) bool {
|
||||
res := false
|
||||
// This one is kinda weird. In C and native backend we can cast booleans and integers to pointers
|
||||
// so we just check *for* all possible NULL-like values here.
|
||||
#if (typeof val == 'function') { res.val = false; } else {
|
||||
#val = val instanceof voidptr ? val.valueOf().val : val;
|
||||
#res.val = val === null || val === undefined || val === false || val === 0 || val === BigInt(0) || (val instanceof int ? val.val == 0 : false)
|
||||
#}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (f float_literal) str() string {
|
||||
res := ''
|
||||
#res.str += f.valueOf()
|
||||
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2019-2024 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
|
||||
|
||||
fn (a any) toString()
|
||||
|
||||
// panic prints an error message, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic(s string) {
|
||||
eprintln('V panic: ' + s)
|
||||
eprintln(js_stacktrace())
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// panic_n prints an error message, followed by the given number, then exits the process with exit code of 1.
|
||||
@[noreturn]
|
||||
pub fn panic_n(s string, n i64) {
|
||||
eprintln('V panic: ' + s)
|
||||
eprintln(js_stacktrace())
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// IError holds information about an error instance.
|
||||
pub interface IError {
|
||||
msg() string
|
||||
code() int
|
||||
}
|
||||
|
||||
// str returns the message of IError.
|
||||
pub fn (err IError) str() string {
|
||||
return match err {
|
||||
None__ {
|
||||
'none'
|
||||
}
|
||||
Error {
|
||||
err.msg()
|
||||
}
|
||||
MessageError {
|
||||
err.str()
|
||||
}
|
||||
else {
|
||||
'${err.type_name()}: ${err.msg()}'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error is the empty default implementation of `IError`.
|
||||
pub struct Error {}
|
||||
|
||||
// msg returns the message of Error.
|
||||
pub fn (err Error) msg() string {
|
||||
return ''
|
||||
}
|
||||
|
||||
// code returns the code of Error.
|
||||
pub fn (err Error) code() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// MessageError is the default implementation of the `IError` interface that is returned by the `error()` function.
|
||||
struct MessageError {
|
||||
pub:
|
||||
msg string
|
||||
code int
|
||||
}
|
||||
|
||||
// str returns the message and code of the MessageError.
|
||||
pub fn (err MessageError) str() string {
|
||||
return err.msg
|
||||
}
|
||||
|
||||
// msg returns the message of the MessageError.
|
||||
pub fn (err MessageError) msg() string {
|
||||
return err.msg
|
||||
}
|
||||
|
||||
// code returns the code of MessageError.
|
||||
pub fn (err MessageError) code() int {
|
||||
return err.code
|
||||
}
|
||||
|
||||
pub const none__ = IError(&None__{})
|
||||
|
||||
struct None__ {
|
||||
Error
|
||||
}
|
||||
|
||||
fn (_ None__) str() string {
|
||||
return 'none'
|
||||
}
|
||||
|
||||
pub struct Option {
|
||||
state u8
|
||||
err IError = none__
|
||||
}
|
||||
|
||||
// str returns the Option type: ok, none, or error.
|
||||
pub fn (o Option) str() string {
|
||||
if o.state == 0 {
|
||||
return 'Option{ ok }'
|
||||
}
|
||||
if o.state == 1 {
|
||||
return 'Option{ none }'
|
||||
}
|
||||
return 'Option{ error: "${o.err}" }'
|
||||
}
|
||||
|
||||
pub struct _option {
|
||||
state u8
|
||||
err IError = none__
|
||||
}
|
||||
|
||||
// str returns the Option type: ok, none, or error.
|
||||
pub fn (o _option) str() string {
|
||||
if o.state == 0 {
|
||||
return 'Option{ ok }'
|
||||
}
|
||||
if o.state == 1 {
|
||||
return 'Option{ none }'
|
||||
}
|
||||
return 'Option{ error: "${o.err}" }'
|
||||
}
|
||||
|
||||
// trace_error prints to stderr a string and a backtrace of the error.
|
||||
fn trace_error(x string) {
|
||||
eprintln('> ${@FN} | ${x}')
|
||||
}
|
||||
|
||||
// error returns a default error instance containing the error given in `message`.
|
||||
// Example: if ouch { return error('an error occurred') }
|
||||
@[inline]
|
||||
pub fn error(message string) IError {
|
||||
// trace_error(message)
|
||||
return &MessageError{
|
||||
msg: message
|
||||
}
|
||||
}
|
||||
|
||||
// error_with_code returns a default error instance containing the given `message` and error `code`.
|
||||
// Example: if ouch { return error_with_code('an error occurred', 1) }
|
||||
@[inline]
|
||||
pub fn error_with_code(message string, code int) IError {
|
||||
// trace_error('${message} | code: ${code}')
|
||||
return &MessageError{
|
||||
msg: message
|
||||
code: code
|
||||
}
|
||||
}
|
||||
|
||||
// free allows for manually freeing memory allocated at the address `ptr`.
|
||||
// However, this is a no-op on JS backend
|
||||
@[unsafe]
|
||||
pub fn free(ptr voidptr) {
|
||||
_ := ptr
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
module builtin
|
||||
|
||||
pub fn (b u8) is_space() bool {
|
||||
mut result := false
|
||||
#result.val = /^\s*$/.test(String.fromCharCode(b))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
pub fn (c u8) str() string {
|
||||
res := ''
|
||||
#res.str = c.val.toString()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (c u8) ascii_str() string {
|
||||
res := ''
|
||||
#res.str = String.fromCharCode(c.val)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (c u8) repeat(count int) string {
|
||||
mut res := ''
|
||||
for _ in 0 .. count {
|
||||
res += c.ascii_str()
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn (c u8) is_digit() bool {
|
||||
return c >= `0` && c <= `9`
|
||||
}
|
||||
|
||||
// is_hex_digit returns `true` if the byte is either in range 0-9, a-f or A-F and `false` otherwise.
|
||||
// Example: assert u8(`F`) == true
|
||||
@[inline]
|
||||
pub fn (c u8) is_hex_digit() bool {
|
||||
return c.is_digit() || (c >= `a` && c <= `f`) || (c >= `A` && c <= `F`)
|
||||
}
|
||||
|
||||
// is_oct_digit returns `true` if the byte is in range 0-7 and `false` otherwise.
|
||||
// Example: assert u8(`7`) == true
|
||||
@[inline]
|
||||
pub fn (c u8) is_oct_digit() bool {
|
||||
return c >= `0` && c <= `7`
|
||||
}
|
||||
|
||||
// is_bin_digit returns `true` if the byte is a binary digit (0 or 1) and `false` otherwise.
|
||||
// Example: assert u8(`0`) == true
|
||||
@[inline]
|
||||
pub fn (c u8) is_bin_digit() bool {
|
||||
return c == `0` || c == `1`
|
||||
}
|
||||
|
||||
// is_letter returns `true` if the byte is in range a-z or A-Z and `false` otherwise.
|
||||
// Example: assert u8(`V`) == true
|
||||
@[inline]
|
||||
pub fn (c u8) is_letter() bool {
|
||||
return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`)
|
||||
}
|
||||
|
||||
// is_alnum returns `true` if the byte is in range a-z, A-Z, 0-9 and `false` otherwise.
|
||||
// Example: assert u8(`V`) == true
|
||||
@[inline]
|
||||
pub fn (c u8) is_alnum() bool {
|
||||
return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || (c >= `0` && c <= `9`)
|
||||
}
|
||||
|
||||
// is_capital returns `true`, if the byte is a Latin capital letter.
|
||||
// Example: assert `H`.is_capital() == true
|
||||
// Example: assert `h`.is_capital() == false
|
||||
@[inline]
|
||||
pub fn (c u8) is_capital() bool {
|
||||
return c >= `A` && c <= `Z`
|
||||
}
|
||||
|
||||
// str_escaped returns the contents of `byte` as an escaped `string`.
|
||||
// Example: assert u8(0).str_escaped() == r'`\0`'
|
||||
|
||||
pub fn (b u8) str_escaped() string {
|
||||
mut str := ''
|
||||
match b {
|
||||
0 { str = r'`\0`' }
|
||||
7 { str = r'`\a`' }
|
||||
8 { str = r'`\b`' }
|
||||
9 { str = r'`\t`' }
|
||||
10 { str = r'`\n`' }
|
||||
11 { str = r'`\v`' }
|
||||
12 { str = r'`\f`' }
|
||||
13 { str = r'`\r`' }
|
||||
27 { str = r'`\e`' }
|
||||
32...126 { str = b.ascii_str() }
|
||||
else { str = '0x' + b.hex() }
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
module builtin
|
||||
|
||||
pub fn (x f32) str() string {
|
||||
res := ''
|
||||
#res.str = x.val + ''
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x f64) str() string {
|
||||
res := ''
|
||||
#res.str = x.val + ''
|
||||
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
module builtin
|
||||
|
||||
pub type byte = u8
|
||||
|
||||
pub const min_i8 = i8(-128)
|
||||
pub const max_i8 = i8(127)
|
||||
|
||||
pub const min_i16 = i16(-32768)
|
||||
pub const max_i16 = i16(32767)
|
||||
|
||||
pub const min_i32 = i32(-2147483648)
|
||||
pub const max_i32 = i32(2147483647)
|
||||
|
||||
// -9223372036854775808 is wrong, because C compilers parse literal values
|
||||
// without sign first, and 9223372036854775808 overflows i64, hence the
|
||||
// consecutive subtraction by 1
|
||||
pub const min_i64 = i64(-9223372036854775807 - 1)
|
||||
pub const max_i64 = i64(9223372036854775807)
|
||||
|
||||
pub const min_int = $if new_int ? && x64 { int(min_i64) } $else { int(min_i32) }
|
||||
pub const max_int = $if new_int ? && x64 { int(max_i64) } $else { int(max_i32) }
|
||||
|
||||
pub const min_u8 = u8(0)
|
||||
pub const max_u8 = u8(255)
|
||||
|
||||
pub const min_u16 = u16(0)
|
||||
pub const max_u16 = u16(65535)
|
||||
|
||||
pub const min_u32 = u32(0)
|
||||
pub const max_u32 = u32(4294967295)
|
||||
|
||||
pub const min_u64 = u64(0)
|
||||
pub const max_u64 = u64(18446744073709551615)
|
||||
|
||||
pub fn (i i8) str() string {
|
||||
mut res := ''
|
||||
#res.str = i.val.toString()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i i16) str() string {
|
||||
mut res := ''
|
||||
#res.str = i.val.toString()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i u16) str() string {
|
||||
mut res := ''
|
||||
#res.str = i.val.toString()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i int) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i+'' )
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i i64) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i + '')
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i u32) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i + '')
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i u64) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i + '')
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i bool) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i + '')
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i any) str() string {
|
||||
mut res := ''
|
||||
#res = new string( i.toString() )
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (i int_literal) str() string {
|
||||
res := ''
|
||||
#res.str = i.val.toString()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x u64) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x u64) hex_full() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x i64) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x u32) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x u16) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x i8) hex() string {
|
||||
mut res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
if res.len < 2 {
|
||||
res = '0' + res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x i16) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x int) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x int_literal) hex() string {
|
||||
res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (x u8) hex() string {
|
||||
mut res := ''
|
||||
#res.str = x.val.toString(16)
|
||||
if res.len < 2 {
|
||||
res = '0' + res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// hex returns a string with the hexadecimal representation of the byte elements of the array.
|
||||
pub fn (b []u8) hex() string {
|
||||
mut hex := ''
|
||||
for i in b {
|
||||
mut z := i
|
||||
z = z
|
||||
#let n0 = i.val >> 4
|
||||
#hex.str += n0 < 10 ? String.fromCharCode(n0) : String.fromCharCode(n0 + 87)
|
||||
|
||||
#let n1 = i.val & 0xF
|
||||
#hex.str += n1 < 10 ? String.fromCharCode(n1) : String.fromCharCode(n1 + 87)
|
||||
}
|
||||
return hex
|
||||
}
|
||||
|
||||
pub fn (i int) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i i8) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i i16) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i i64) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i u8) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i u16) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i u32) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
|
||||
pub fn (i u64) hex2() string {
|
||||
return '0x' + i.hex()
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
// vtest retry: 3
|
||||
// vtest build: present_node?
|
||||
|
||||
const a = 3
|
||||
const u = u64(1)
|
||||
|
||||
fn test_const() {
|
||||
b := (true && true) || false
|
||||
assert b == true
|
||||
assert a == 3
|
||||
assert u == u64(1)
|
||||
assert u == 1 // make sure this works without the cast
|
||||
}
|
||||
|
||||
fn test_str_methods() {
|
||||
assert i8(1).str() == '1'
|
||||
assert i8(-1).str() == '-1'
|
||||
assert i16(1).str() == '1'
|
||||
assert i16(-1).str() == '-1'
|
||||
assert int(1).str() == '1'
|
||||
assert int(-1).str() == '-1'
|
||||
assert int(2147483647).str() == '2147483647'
|
||||
// todo: overflow check for integers
|
||||
// assert int(2147483648).str() == '-2147483648'
|
||||
// assert int(-2147483648).str() == '-2147483648'
|
||||
assert i64(1).str() == '1'
|
||||
assert i64(-1).str() == '-1'
|
||||
assert u16(1).str() == '1'
|
||||
// assert u16(-1).str() == '65535'
|
||||
assert u32(1).str() == '1'
|
||||
// assert u32(-1).str() == '4294967295'
|
||||
assert u64(1).str() == '1'
|
||||
// assert u64(-1).str() == '18446744073709551615'
|
||||
}
|
||||
|
||||
fn test_and_precedence() {
|
||||
assert (2 & 0 == 0) == ((2 & 0) == 0)
|
||||
assert (2 & 0 != 0) == ((2 & 0) != 0)
|
||||
assert (0 & 0 >= 0) == ((0 & 0) >= 0)
|
||||
assert (0 & 0 <= 0) == ((0 & 0) <= 0)
|
||||
assert (0 & 0 < 1) == ((0 & 0) < 1)
|
||||
assert (1 & 2 > 0) == ((1 & 2) > 0)
|
||||
}
|
||||
|
||||
fn test_or_precedence() {
|
||||
assert (1 | 0 == 0) == ((1 | 0) == 0)
|
||||
assert (1 | 0 != 1) == ((1 | 0) != 1)
|
||||
assert (1 | 0 >= 2) == ((1 | 0) >= 2)
|
||||
assert (1 | 0 <= 0) == ((1 | 0) <= 0)
|
||||
assert (1 | 0 < 0) == ((1 | 0) < 0)
|
||||
assert (1 | 0 > 1) == ((1 | 0) > 1)
|
||||
}
|
||||
|
||||
fn test_xor_precedence() {
|
||||
assert (1 ^ 0 == 2) == ((1 ^ 0) == 2)
|
||||
assert (1 ^ 0 != 2) == ((1 ^ 0) != 2)
|
||||
assert (1 ^ 0 >= 0) == ((1 ^ 0) >= 0)
|
||||
assert (1 ^ 0 <= 1) == ((1 ^ 0) <= 1)
|
||||
assert (1 ^ 0 < 0) == ((1 ^ 0) < 0)
|
||||
assert (1 ^ 0 > 1) == ((1 ^ 0) > 1)
|
||||
}
|
||||
|
||||
fn test_left_shift_precedence() {
|
||||
assert (2 << 4 | 3) == ((2 << 4) | 3)
|
||||
assert (2 << 4 | 3) != (2 << (4 | 3))
|
||||
}
|
||||
|
||||
fn test_right_shift_precedence() {
|
||||
assert (256 >> 4 | 3) == ((256 >> 4) | 3)
|
||||
assert (256 >> 4 | 3) != (256 >> (4 | 3))
|
||||
}
|
||||
|
||||
fn test_i8_print() {
|
||||
b := i8(0)
|
||||
println(b)
|
||||
c := i16(7)
|
||||
println(c)
|
||||
d := u16(6)
|
||||
println(d)
|
||||
assert true
|
||||
}
|
||||
|
||||
/*
|
||||
fn test_cmp() {
|
||||
assert 1 ≠ 2
|
||||
assert 1 ⩽ 2
|
||||
assert 1 ⩾ 0
|
||||
}
|
||||
*/
|
||||
type MyInt = int
|
||||
|
||||
fn test_int_alias() {
|
||||
i := MyInt(2)
|
||||
assert i + 10 == 12
|
||||
}
|
||||
|
||||
fn test_hex() {
|
||||
x := u64(10)
|
||||
assert x.hex() == 'a'
|
||||
b := 1234
|
||||
assert b.hex() == '4d2'
|
||||
b1 := -1
|
||||
println(b1)
|
||||
// assert b1.hex() == 'ffffffff'
|
||||
// unsigned tests
|
||||
// assert u8(12).hex() == '0c'
|
||||
// assert u8(255).hex() == 'ff'
|
||||
assert u16(65535).hex() == 'ffff'
|
||||
// assert u32(-1).hex() == 'ffffffff'
|
||||
// assert u64(-1).hex() == 'ffffffffffffffff'
|
||||
// signed tests
|
||||
// assert i8(-1).hex() == 'ff'
|
||||
assert i8(12).hex() == '0c'
|
||||
assert i16(32767).hex() == '7fff'
|
||||
assert int(2147483647).hex() == '7fffffff'
|
||||
assert i64(9223372036854775807).hex() == '7fffffffffffffff'
|
||||
}
|
||||
|
||||
fn test_bin() {
|
||||
x1 := 0b10
|
||||
assert x1 == 2
|
||||
x2 := 0b10101010
|
||||
assert x2 == 0xAA
|
||||
x3 := -0b0000001
|
||||
assert x3 == -1
|
||||
x4 := 0b11111111
|
||||
assert x4 == 255
|
||||
x5 := u8(0b11111111)
|
||||
assert x5 == 255
|
||||
x6 := char(0b11111111)
|
||||
assert int(x6) == -1
|
||||
x7 := 0b0
|
||||
assert x7 == 0
|
||||
x8 := -0b0
|
||||
assert x8 == 0
|
||||
}
|
||||
|
||||
fn test_oct() {
|
||||
x1 := 0o12
|
||||
assert x1 == 10
|
||||
x2 := 0o350
|
||||
assert x2 == 232
|
||||
x3 := 0o00073
|
||||
assert x3 == 59
|
||||
x4 := 0
|
||||
assert x4 == 0
|
||||
x5 := 195
|
||||
assert x5 == 195
|
||||
x6 := -0o744
|
||||
assert x6 == -484
|
||||
x7 := -0o000042
|
||||
assert x7 == -34
|
||||
x8 := -112
|
||||
assert x8 == -112
|
||||
x9 := -0
|
||||
assert x9 == 0
|
||||
}
|
||||
|
||||
fn test_num_separator() {
|
||||
// int
|
||||
assert 100_000_0 == 1000000
|
||||
assert -2_23_4_6 == -22346
|
||||
|
||||
// bin
|
||||
assert 0b0_11 == 3
|
||||
assert -0b0_100 == -4
|
||||
|
||||
// oct
|
||||
assert 0o1_73 == 123
|
||||
assert -0o17_5 == -125
|
||||
assert -0o175 == -125
|
||||
|
||||
// hex
|
||||
assert 0xFF == 255
|
||||
assert 0xF_F == 255
|
||||
|
||||
// f32 or f64
|
||||
assert 312_2.55 == 3122.55
|
||||
assert 312_2.55 == 3122.55
|
||||
}
|
||||
|
||||
fn test_int_decl() {
|
||||
x1 := 0
|
||||
x2 := 1333
|
||||
x3 := -88955
|
||||
x4 := 2000000000
|
||||
x5 := -1999999999
|
||||
assert typeof(x1).name == 'int'
|
||||
assert typeof(x2).name == 'int'
|
||||
assert typeof(x3).name == 'int'
|
||||
assert typeof(x4).name == 'int'
|
||||
assert typeof(x5).name == 'int'
|
||||
x7 := u64(-321314588900011)
|
||||
assert typeof(x7).name == 'u64'
|
||||
}
|
||||
|
||||
fn test_int_to_hex() {
|
||||
// array hex
|
||||
/*
|
||||
st := [u8(`V`), `L`, `A`, `N`, `G`]
|
||||
assert st.hex() == '564c414e47'
|
||||
assert st.hex().len == 10
|
||||
st1 := [u8(0x41)].repeat(100)
|
||||
assert st1.hex() == '41'.repeat(100)*/
|
||||
// --- int to hex tests
|
||||
c := 12
|
||||
// 8Bit
|
||||
assert u8(0).hex() == '00'
|
||||
assert u8(c).hex() == '0c'
|
||||
assert i8(c).hex() == '0c'
|
||||
assert u8(127).hex() == '7f'
|
||||
assert i8(127).hex() == '7f'
|
||||
assert u8(255).hex() == 'ff'
|
||||
// assert u8(-1).hex() == 'ff'
|
||||
// 16bit
|
||||
assert u16(0).hex() == '0'
|
||||
assert i16(c).hex() == 'c'
|
||||
assert u16(c).hex() == 'c'
|
||||
assert i16(32767).hex() == '7fff'
|
||||
assert u16(32767).hex() == '7fff'
|
||||
// assert i16(-1).hex() == 'ffff'
|
||||
assert u16(65535).hex() == 'ffff'
|
||||
// 32bit
|
||||
assert u32(0).hex() == '0'
|
||||
assert c.hex() == 'c'
|
||||
assert u32(c).hex() == 'c'
|
||||
assert 2147483647.hex() == '7fffffff'
|
||||
assert u32(2147483647).hex() == '7fffffff'
|
||||
// assert (-1).hex() == 'ffffffffffffffff'
|
||||
// assert u32(4294967295).hex() == 'ffffffff'
|
||||
// 64 bit
|
||||
assert u64(0).hex() == '0'
|
||||
assert i64(c).hex() == 'c'
|
||||
assert u64(c).hex() == 'c'
|
||||
assert i64(9223372036854775807).hex() == '7fffffffffffffff'
|
||||
assert u64(9223372036854775807).hex() == '7fffffffffffffff'
|
||||
// assert i64(-1).hex() == 'ffffffffffffffff'
|
||||
assert u64(18446744073709551615).hex() == 'ffffffffffffffff'
|
||||
}
|
||||
|
||||
fn test_repeat() {
|
||||
b := u8(`V`)
|
||||
assert b.repeat(5) == 'VVVVV'
|
||||
assert b.repeat(1) == b.ascii_str()
|
||||
assert b.repeat(0) == ''
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This file contains JS functions present in both node and the browser.
|
||||
// They have been ported from their TypeScript definitions.
|
||||
|
||||
module builtin
|
||||
|
||||
pub interface JS.Object {}
|
||||
|
||||
@[single_impl]
|
||||
pub interface JS.BigInt {
|
||||
JS.Any
|
||||
}
|
||||
|
||||
@[single_impl]
|
||||
pub interface JS.Number {
|
||||
JS.Any
|
||||
}
|
||||
|
||||
pub interface JS.RegExp {
|
||||
JS.Any
|
||||
}
|
||||
|
||||
pub type SplitSeparator = JS.RegExp | JS.String
|
||||
|
||||
@[single_impl]
|
||||
pub interface JS.String {
|
||||
JS.Any
|
||||
length JS.Number
|
||||
charAt(index JS.Number) JS.String
|
||||
charCodeAt(index JS.Number) JS.Number
|
||||
toUpperCase() JS.String
|
||||
toLowerCase() JS.String
|
||||
concat(a JS.String) JS.String
|
||||
includes(substr JS.String) JS.Boolean
|
||||
endsWith(substr JS.String) JS.Boolean
|
||||
startsWith(substr JS.String) JS.Boolean
|
||||
slice(a JS.Number, b JS.Number) JS.String
|
||||
split(delim SplitSeparator) JS.Array
|
||||
indexOf(needle JS.String) JS.Number
|
||||
lastIndexOf(needle JS.String) JS.Number
|
||||
}
|
||||
|
||||
@[single_impl]
|
||||
pub interface JS.Boolean {
|
||||
JS.Any
|
||||
length JS.Number
|
||||
}
|
||||
|
||||
pub interface JS.Map {
|
||||
JS.Any
|
||||
size JS.Number
|
||||
clear()
|
||||
delete(key JS.Any) JS.Boolean
|
||||
get(key JS.Any) JS.Any
|
||||
has(key JS.Any) JS.Any
|
||||
set(key JS.Any, val JS.Any)
|
||||
}
|
||||
|
||||
#function Any(val) { return val; }
|
||||
|
||||
pub interface JS.Any {}
|
||||
|
||||
pub fn js_is_null(x JS.Any) bool {
|
||||
res := false
|
||||
#res.val = x === null
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn js_is_undefined(x JS.Any) bool {
|
||||
res := false
|
||||
#res.val = x === undefined
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn js_null() JS.Any {
|
||||
mut obj := JS.Any{}
|
||||
#obj = null;
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
pub fn js_undefined() JS.Any {
|
||||
mut obj := JS.Any{}
|
||||
#obj = undefined;
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
pub interface JS.Array {
|
||||
JS.Any // map(fn (JS.Any) JS.Any) JS.Array
|
||||
map(JS.Any) JS.Array
|
||||
push(JS.Any) JS.Any
|
||||
pop() JS.Any
|
||||
at(JS.Number) JS.Any
|
||||
mut:
|
||||
length JS.Number
|
||||
}
|
||||
|
||||
pub fn JS.Array.prototype.constructor(...any) JS.Array
|
||||
|
||||
// browser: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Error
|
||||
// node: https://nodejs.org/api/errors.html#errors_class_error
|
||||
pub struct JS.Error {
|
||||
pub:
|
||||
name string
|
||||
message string
|
||||
stack string
|
||||
}
|
||||
|
||||
// Type prototype functions
|
||||
fn (v JS.String) toString() JS.String
|
||||
fn (v JS.Number) toString() JS.String
|
||||
fn (v JS.Boolean) toString() JS.String
|
||||
fn (v JS.Array) toString() JS.String
|
||||
fn (v JS.Map) toString() JS.String
|
||||
|
||||
// Hack for "`[]JS.String` is not a struct" when returning arr.length or arr.len
|
||||
// TODO: Fix []JS.String not a struct error
|
||||
fn native_str_arr_len(arr []JS.String) int {
|
||||
mut len := 0
|
||||
#len = arr.length
|
||||
|
||||
return len
|
||||
}
|
||||
|
||||
// Top level functions
|
||||
fn JS.eval(JS.String) JS.Any
|
||||
fn JS.parseInt(JS.String, f64) JS.Number
|
||||
fn JS.parseFloat(JS.String) JS.Number
|
||||
fn JS.isNaN(f64) bool
|
||||
fn JS.isFinite(f64) bool
|
||||
fn JS.decodeURI(JS.String) JS.String
|
||||
fn JS.decodeURIComponent(JS.String) JS.String
|
||||
fn JS.encodeURI(JS.String) JS.String
|
||||
|
||||
type EncodeURIComponentArg = JS.String | bool | f64
|
||||
|
||||
fn JS.encodeURIComponent(EncodeURIComponentArg) JS.String
|
||||
fn JS.escape(JS.String) JS.String
|
||||
fn JS.unescape(JS.String) JS.String
|
||||
|
||||
// console
|
||||
fn JS.console.assert(bool, ...any)
|
||||
fn JS.console.clear()
|
||||
fn JS.console.count(JS.String)
|
||||
fn JS.console.countReset(JS.String)
|
||||
fn JS.console.debug(...any)
|
||||
fn JS.console.dir(any, any)
|
||||
fn JS.console.dirxml(...any)
|
||||
fn JS.console.error(...any)
|
||||
fn JS.console.exception(string, ...any)
|
||||
fn JS.console.group(...any)
|
||||
fn JS.console.groupCollapsed(...any)
|
||||
fn JS.console.groupEnd()
|
||||
fn JS.console.info(...any)
|
||||
fn JS.console.log(...any)
|
||||
fn JS.console.table(any, []string)
|
||||
fn JS.console.time(JS.String)
|
||||
fn JS.console.timeEnd(JS.String)
|
||||
fn JS.console.timeLog(string, ...any)
|
||||
fn JS.console.timeStamp(string)
|
||||
fn JS.console.trace(...any)
|
||||
fn JS.console.warn(...any)
|
||||
|
||||
// Math
|
||||
fn JS.Math.abs(f64) f64
|
||||
fn JS.Math.acos(f64) f64
|
||||
fn JS.Math.asin(f64) f64
|
||||
fn JS.Math.atan(f64) f64
|
||||
fn JS.Math.atan2(f64, f64) f64
|
||||
fn JS.Math.ceil(f64) f64
|
||||
fn JS.Math.cos(f64) f64
|
||||
fn JS.Math.exp(f64) f64
|
||||
fn JS.Math.floor(f64) f64
|
||||
fn JS.Math.log(f64) f64
|
||||
fn JS.Math.max(...f64) f64
|
||||
fn JS.Math.min(...f64) f64
|
||||
fn JS.Math.pow(f64, f64) f64
|
||||
fn JS.Math.random() f64
|
||||
fn JS.Math.round(f64) f64
|
||||
fn JS.Math.sin(f64) f64
|
||||
fn JS.Math.sqrt(f64) f64
|
||||
fn JS.Math.tan(f64) f64
|
||||
|
||||
// JSON
|
||||
fn JS.JSON.stringify(any) JS.String
|
||||
fn JS.JSON.parse(string) any
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This file contains JS functions only present in the browser.
|
||||
// They have been ported from their TypeScript definitions.
|
||||
|
||||
module builtin
|
||||
|
||||
// Window
|
||||
fn JS.atob(string) string
|
||||
fn JS.btoa(string) string
|
||||
fn JS.clearInterval(int)
|
||||
fn JS.clearTimeout(int)
|
||||
|
||||
// fn JS.createImageBitmap(ImageBitmapSource, ImageBitmapOptions) Promise<ImageBitmap>
|
||||
// fn JS.createImageBitmap(ImageBitmapSource, int, int, int, int, ImageBitmapOptions) Promise<ImageBitmap>
|
||||
|
||||
// TODO: js async attribute
|
||||
// [js_async]
|
||||
// fn JS.fetch(RequestInfo, RequestInit) Promise<Response>
|
||||
fn JS.queueMicrotask(fn ())
|
||||
fn JS.setInterval(any, int, ...any) int
|
||||
fn JS.setTimeout(any, int, ...any) int
|
||||
|
||||
fn JS.alert(any)
|
||||
fn JS.blur()
|
||||
fn JS.captureEvents()
|
||||
fn JS.close()
|
||||
fn JS.confirm(string) bool
|
||||
|
||||
// fn JS.departFocus(NavigationReason, FocusNavigationOrigin)
|
||||
fn JS.focus()
|
||||
|
||||
// fn JS.getComputedStyle(Element, string | null) CSSStyleDeclaration
|
||||
// fn JS.getMatchedCSSRules(Element, string | null) CSSRuleList
|
||||
// fn JS.getSelection() Selection | null
|
||||
// fn JS.matchMedia(string) MediaQueryList
|
||||
fn JS.moveBy(int, int)
|
||||
fn JS.moveTo(int, int)
|
||||
fn JS.msWriteProfilerMark(string)
|
||||
|
||||
// fn JS.open(string, string, string, bool)?Window
|
||||
// fn JS.postMessage(any, string, []Transferable)
|
||||
fn JS.print()
|
||||
fn JS.prompt(string, string) ?string
|
||||
fn JS.releaseEvents()
|
||||
fn JS.resizeBy(int, int)
|
||||
fn JS.resizeTo(int, int)
|
||||
|
||||
// fn JS.scroll(ScrollToOptions)
|
||||
fn JS.scroll(int, int)
|
||||
|
||||
// fn JS.scrollBy(ScrollToOptions)
|
||||
fn JS.scrollBy(int, int)
|
||||
|
||||
// fn JS.scrollTo(ScrollToOptions)
|
||||
fn JS.scrollTo(int, int)
|
||||
fn JS.stop()
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This file contains JS functions only present in node.js.
|
||||
// They have been ported from their TypeScript definitions.
|
||||
|
||||
module builtin
|
||||
|
||||
pub struct JS.node_process {
|
||||
pub:
|
||||
arch string
|
||||
argsv []string
|
||||
env []string
|
||||
platform string
|
||||
version string
|
||||
// TODO: add all properties
|
||||
}
|
||||
|
||||
// hack to access process properties
|
||||
pub fn js_node_process() JS.node_process {
|
||||
#return process
|
||||
|
||||
return JS.node_process{}
|
||||
}
|
||||
|
||||
fn JS.process.exit(int)
|
||||
fn JS.process.stdout.write(string) bool
|
||||
fn JS.process.stdout.writeln(string) bool
|
||||
fn JS.process.stderr.write(string) bool
|
||||
fn JS.process.stderr.writeln(string) bool
|
||||
@@ -0,0 +1,94 @@
|
||||
module builtin
|
||||
|
||||
struct map {
|
||||
m JS.Map
|
||||
pub:
|
||||
len int
|
||||
}
|
||||
|
||||
fn (mut m map) internal_set(key JS.Any, val JS.Any) {
|
||||
//$if es5 {
|
||||
#let skey = key;
|
||||
#if (key != null && typeof key.$toJS === 'function') key = key.$toJS();
|
||||
#if (!(key in m.val.map)) {
|
||||
#m.val.length++;
|
||||
#m.val.map[key] = { key: skey, val: val };
|
||||
#} else {
|
||||
#m.val.map[key].val = val
|
||||
#}
|
||||
/*} $else {
|
||||
# if (key.hasOwnProperty('$toJS')) key = key.$toJS();
|
||||
# m.val.m.set(key,val);
|
||||
}*/
|
||||
_ := key
|
||||
_ := val
|
||||
}
|
||||
|
||||
fn (mut m map) internal_get(key JS.Any) JS.Any {
|
||||
mut val := JS.Any(unsafe { nil })
|
||||
//$if es5 {
|
||||
#if (typeof key != "string" && key != null && typeof key.$toJS === 'function') key = key.$toJS();
|
||||
#if (key in m.val.map) {
|
||||
#val = m.val.map[key].val
|
||||
#} else {
|
||||
#val = js_undefined()
|
||||
#}
|
||||
/*} $else {
|
||||
# if (key.hasOwnProperty('$toJS')) key = key.$toJS();
|
||||
# val = m.val.m.get(key)
|
||||
}*/
|
||||
_ := key
|
||||
return val
|
||||
}
|
||||
|
||||
#map.prototype.get = function (key) { return map_internal_get(this,key); }
|
||||
#map.prototype.set = function(key,val) { map_internal_set(this,key,val); }
|
||||
#map.prototype.has = function (key) { if (typeof key != "string" && key != null && typeof key.$toJS === 'function') { key = key.$toJS() } return key in this.map; }
|
||||
// Removes the mapping of a particular key from the map.
|
||||
@[unsafe]
|
||||
pub fn (mut m map) delete(key JS.Any) {
|
||||
#let k = key != null && typeof key.$toJS === 'function' ? key.$toJS() : key;
|
||||
|
||||
#if (k in m.val.map) {
|
||||
#delete m.val.map[k];
|
||||
#m.val.length--;
|
||||
#}
|
||||
|
||||
_ := key
|
||||
}
|
||||
|
||||
pub fn (m map) clone() map {
|
||||
mut res := m
|
||||
#res = v_clone_value(m)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (m &map) free() {}
|
||||
|
||||
pub fn (m map) keys() array {
|
||||
ret := JS.makeEmptyArray()
|
||||
#for (var key in m.map) array_push(ret,m.map[key].key,false)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
pub fn (m map) values() array {
|
||||
ret := JS.makeEmptyArray()
|
||||
#for (var key in m.map) array_push(ret,m.map[key].val,false);
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
//#Object.defineProperty(map.prototype,"len",{get: function() { return this.map.size; }})
|
||||
#map.prototype.toString = function () {
|
||||
#function fmtKey(key) { return typeof key == 'string' ? '\'' + key + '\'' : key}
|
||||
#let res = '{'
|
||||
#for (const entry of this) {
|
||||
#res += fmtKey(entry[0]) + ': ' + entry[0];
|
||||
#}
|
||||
#res += '}'
|
||||
#return res;
|
||||
#}
|
||||
|
||||
#map.prototype.getOrSet = function (key, init) { const skey = key; if (typeof key != "string" && key != null && typeof key.$toJS === 'function') { key = key.$toJS() } if (key in this.map) { return this.map[key].val; } this.length++; this.map[key] = { key: skey, val: init }; return this.map[key].val; }
|
||||
@@ -0,0 +1,972 @@
|
||||
// vtest retry: 3
|
||||
// vtest build: present_node?
|
||||
import rand
|
||||
|
||||
const test_strings = unique_strings(200, 10)
|
||||
|
||||
fn unique_strings(arr_len int, str_len int) []string {
|
||||
mut arr := []string{cap: arr_len}
|
||||
for arr.len < arr_len {
|
||||
str := rand.string(str_len)
|
||||
if str !in arr {
|
||||
arr << str
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
fn test_get_and_set_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in test_strings {
|
||||
m[s] = i
|
||||
assert m[s] == i
|
||||
assert m.len == i + 1
|
||||
}
|
||||
for i, s in test_strings {
|
||||
assert m[s] == i
|
||||
}
|
||||
assert m.len == test_strings.len
|
||||
}
|
||||
|
||||
fn test_for_in_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in test_strings {
|
||||
m[s] = i
|
||||
}
|
||||
for k, v in m {
|
||||
assert m[k] == v
|
||||
}
|
||||
}
|
||||
|
||||
fn test_keys_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in test_strings {
|
||||
m[s] = i
|
||||
}
|
||||
keys := m.keys()
|
||||
assert keys.len == test_strings.len
|
||||
assert keys.len == m.len
|
||||
assert keys == test_strings
|
||||
}
|
||||
|
||||
fn test_deletes_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in test_strings {
|
||||
m[s] = i
|
||||
}
|
||||
for i, s in test_strings {
|
||||
m.delete(s)
|
||||
assert m[s] == 0
|
||||
assert m.len == test_strings.len - (i + 1)
|
||||
}
|
||||
assert m.len == 0
|
||||
assert m.keys().len == 0
|
||||
}
|
||||
|
||||
struct User {
|
||||
mut:
|
||||
name string
|
||||
}
|
||||
|
||||
struct Aaa {
|
||||
mut:
|
||||
m map[string]int
|
||||
users map[string]User
|
||||
}
|
||||
|
||||
fn (mut a Aaa) set(key string, val int) {
|
||||
a.m[key] = val
|
||||
}
|
||||
|
||||
fn test_map() {
|
||||
mut m := map[string]int{}
|
||||
assert m.len == 0
|
||||
m['hi'] = 80
|
||||
m['hello'] = 101
|
||||
assert m['hi'] == 80
|
||||
assert m['hello'] == 101
|
||||
assert m.len == 2
|
||||
assert 'hi' in m
|
||||
mut sum := 0
|
||||
// Test `for in`
|
||||
for _, val in m {
|
||||
sum += val
|
||||
}
|
||||
assert sum == 80 + 101
|
||||
// Test `.keys()`
|
||||
keys := m.keys()
|
||||
assert keys.len == 2
|
||||
assert 'hi' in keys
|
||||
assert 'hello' in keys
|
||||
m.delete('hi')
|
||||
assert m.len == 1
|
||||
m.delete('aloha')
|
||||
assert m.len == 1
|
||||
assert m['hi'] == 0
|
||||
assert m.keys().len == 1
|
||||
assert m.keys()[0] == 'hello'
|
||||
// //
|
||||
mut users := map[string]User{}
|
||||
users['1'] = User{'Peter'}
|
||||
peter := users['1']
|
||||
assert peter.name == 'Peter'
|
||||
mut a := Aaa{
|
||||
m: map[string]int{}
|
||||
users: map[string]User{}
|
||||
}
|
||||
a.users['Bob'] = User{'Bob'}
|
||||
q := a.users['Bob']
|
||||
assert q.name == 'Bob'
|
||||
// test struct field change
|
||||
a.users['Bob'].name = 'bob'
|
||||
q2 := a.users['Bob']
|
||||
assert q2.name == 'bob'
|
||||
a.m['one'] = 1
|
||||
a.set('two', 2)
|
||||
assert a.m['one'] == 1
|
||||
assert a.m['two'] == 2
|
||||
}
|
||||
|
||||
fn test_map_init() {
|
||||
one := 'one'
|
||||
three := 'three'
|
||||
m := {
|
||||
one: 1
|
||||
'two': 2
|
||||
three: 1 + 2
|
||||
}
|
||||
assert m['one'] == 1
|
||||
assert m['two'] == 2
|
||||
assert m['three'] == 3
|
||||
assert m['unknown'] == 0
|
||||
}
|
||||
|
||||
fn test_string_map() {
|
||||
// m := map[string]Fn
|
||||
}
|
||||
|
||||
fn test_large_map() {
|
||||
// ticks := time.ticks()
|
||||
mut nums := map[string]int{}
|
||||
n := 30 * 1000
|
||||
for i in 0 .. n {
|
||||
key := i.str()
|
||||
nums[key] = i
|
||||
}
|
||||
assert nums['1'] == 1
|
||||
assert nums['999'] == 999
|
||||
assert nums['1000000'] == 0
|
||||
// println(time.ticks() - ticks)
|
||||
}
|
||||
|
||||
fn test_various_map_value() {
|
||||
mut m1 := map[string]int{}
|
||||
m1['test'] = 1
|
||||
assert m1['test'] == 1
|
||||
mut m2 := map[string]string{}
|
||||
m2['test'] = 'test'
|
||||
assert m2['test'] == 'test'
|
||||
mut m3 := map[string]i8{}
|
||||
m3['test'] = i8(0)
|
||||
assert m3['test'] == i8(0)
|
||||
mut m4 := map[string]i16{}
|
||||
m4['test'] = i16(0)
|
||||
assert m4['test'] == i16(0)
|
||||
mut m7 := map[string]u16{}
|
||||
m7['test'] = u16(0)
|
||||
assert m7['test'] == u16(0)
|
||||
mut m8 := map[string]u32{}
|
||||
m8['test'] = u32(0)
|
||||
assert m8['test'] == u32(0)
|
||||
mut m9 := map[string]bool{}
|
||||
m9['test'] = true
|
||||
assert m9['test'] == true
|
||||
mut m10 := map[string]u8{}
|
||||
m10['test'] = u8(0)
|
||||
assert m10['test'] == u8(0)
|
||||
mut m11 := map[string]f32{}
|
||||
m11['test'] = f32(0.0)
|
||||
assert m11['test'] == f32(0.0)
|
||||
mut m12 := map[string]f64{}
|
||||
m12['test'] = f64(0.0)
|
||||
assert m12['test'] == f64(0.0)
|
||||
// mut m13 := map[string]rune
|
||||
// m13['test'] = rune(0)
|
||||
// assert m13['test'] == rune(0)
|
||||
// todo(playX): pointer equality does not work yet
|
||||
/*
|
||||
mut m14 := map[string]voidptr{}
|
||||
m14['test'] = voidptr(0)
|
||||
assert m14['test'] == voidptr(0)
|
||||
mut m15 := map[string]&byte{}
|
||||
m15['test'] = &u8(unsafe { nil })
|
||||
assert m15['test'] == &u8(unsafe { nil })
|
||||
mut m16 := map[string]i64{}
|
||||
m16['test'] = i64(0)
|
||||
assert m16['test'] == i64(0)
|
||||
mut m17 := map[string]u64{}
|
||||
m17['test'] = u64(0)
|
||||
assert m17['test'] == u64(0)
|
||||
mut m18 := map[string]&int{}
|
||||
m18['test'] = &int(0)
|
||||
assert m18['test'] == &int(0)*/
|
||||
}
|
||||
|
||||
fn test_string_arr() {
|
||||
mut m := map[string][]string{}
|
||||
m['a'] = ['one', 'two']
|
||||
assert m['a'].len == 2
|
||||
assert m['a'][0] == 'one'
|
||||
assert m['a'][1] == 'two'
|
||||
}
|
||||
|
||||
fn mut_map(mut m map[string]int) {
|
||||
m['a'] = 10
|
||||
}
|
||||
|
||||
fn test_mut_arg() {
|
||||
mut m := map[string]int{}
|
||||
mut_map(mut m)
|
||||
a := m['a']
|
||||
assert a == 10
|
||||
}
|
||||
|
||||
fn test_delete() {
|
||||
mut m := map[string]int{}
|
||||
m['one'] = 1
|
||||
m['two'] = 2
|
||||
println(m['two']) // => "2"
|
||||
m.delete('two')
|
||||
println(m['two'].str()) // => 0
|
||||
assert ('two' in m) == false
|
||||
println('two' in m) // => true, on Linux and Windows <-- wrong !
|
||||
}
|
||||
|
||||
fn test_delete_size() {
|
||||
arr := ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||||
mut m := map[string]int{}
|
||||
for _ in 0 .. 10 {
|
||||
for i in 0 .. 10 {
|
||||
m[arr[i]] = i
|
||||
}
|
||||
assert m.len == 10
|
||||
println(m.len)
|
||||
for i in 0 .. 10 {
|
||||
m.delete(arr[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_nested_for_in() {
|
||||
mut m := map[string]int{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i
|
||||
}
|
||||
mut i := 0
|
||||
for key1, _ in m {
|
||||
assert key1 == i.str()
|
||||
i++
|
||||
mut j := 0
|
||||
for key2, _ in m {
|
||||
assert key2 == j.str()
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_delete_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
assert key == i.str()
|
||||
m.delete(key)
|
||||
i++
|
||||
}
|
||||
assert m.str() == '{}'
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
// TODO: for in loop does not work as expected there
|
||||
/*
|
||||
fn test_set_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 10 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut last_key := ''
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
m['10'] = '10'
|
||||
assert key == i.str()
|
||||
last_key = key
|
||||
i++
|
||||
}
|
||||
assert last_key == '10'
|
||||
}
|
||||
*/
|
||||
fn test_delete_and_set_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
assert key == i.str()
|
||||
m.delete(key)
|
||||
m[key] = i.str()
|
||||
if i == 999 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
assert m.len == 1000
|
||||
i = 0
|
||||
for key, _ in m {
|
||||
assert m[key] == i.str()
|
||||
i++
|
||||
}
|
||||
assert i == 1000
|
||||
}
|
||||
|
||||
struct Mstruct1 {
|
||||
pub mut:
|
||||
mymap map[string]int
|
||||
}
|
||||
|
||||
struct Mstruct2 {
|
||||
pub mut:
|
||||
mymap map[string]f64
|
||||
}
|
||||
|
||||
struct Mstruct3 {
|
||||
pub mut:
|
||||
mymap map[string]u16
|
||||
}
|
||||
|
||||
fn test_map_assign() {
|
||||
mut a := map[string]f64{}
|
||||
mut b := map[string]int{}
|
||||
mut c := map[string]u16{}
|
||||
a = {
|
||||
'x': 12.4
|
||||
'y': 3
|
||||
}
|
||||
b = {
|
||||
'u': -13
|
||||
'v': 12
|
||||
}
|
||||
c = {
|
||||
's': u16(5)
|
||||
't': 3
|
||||
}
|
||||
_ := Mstruct1{{
|
||||
'p': 12
|
||||
}}
|
||||
_ := Mstruct2{{
|
||||
'q': 1.7
|
||||
}}
|
||||
_ := Mstruct3{{
|
||||
'r': u16(6)
|
||||
's': 5
|
||||
}}
|
||||
println(a)
|
||||
println(b)
|
||||
println(c)
|
||||
}
|
||||
|
||||
fn test_postfix_op_directly() {
|
||||
mut a := map[string]int{}
|
||||
a['aaa']++
|
||||
assert a['aaa'] == 1
|
||||
a['aaa']++
|
||||
assert a['aaa'] == 2
|
||||
a['bbb']--
|
||||
assert a['bbb'] == -1
|
||||
a['bbb']--
|
||||
assert a['bbb'] == -2
|
||||
}
|
||||
|
||||
fn test_map_push_directly() {
|
||||
mut a := map[string][]string{}
|
||||
a['aaa'] = []string{}
|
||||
a['aaa'] << ['a', 'b', 'c']
|
||||
assert a['aaa'].len == 3
|
||||
assert a['aaa'] == ['a', 'b', 'c']
|
||||
}
|
||||
|
||||
fn test_map_push_missing_key_does_not_insert() {
|
||||
mut a := map[string][]string{}
|
||||
a['aaa'] << 'a'
|
||||
assert a == map[string][]string{}
|
||||
}
|
||||
|
||||
fn test_assign_directly() {
|
||||
mut a := map[string]int{}
|
||||
a['aaa'] += 4
|
||||
assert a['aaa'] == 4
|
||||
a['aaa'] -= 2
|
||||
assert a['aaa'] == 2
|
||||
}
|
||||
|
||||
fn test_map_in_directly() {
|
||||
for k, v in {
|
||||
'aa': 1
|
||||
} {
|
||||
assert k == 'aa'
|
||||
assert v == 1
|
||||
}
|
||||
}
|
||||
|
||||
fn test_plus_assign_string() {
|
||||
mut m := {
|
||||
'one': ''
|
||||
}
|
||||
m['one'] += '1'
|
||||
assert m.len == 1
|
||||
assert m['one'] == '1'
|
||||
}
|
||||
|
||||
fn test_map_keys_to_array() {
|
||||
m := {
|
||||
'a': 'b'
|
||||
'c': 'd'
|
||||
}
|
||||
mut arr := []string{}
|
||||
for k, _ in m {
|
||||
arr << k
|
||||
}
|
||||
sarr := arr.str()
|
||||
println(sarr)
|
||||
assert sarr == "['a', 'c']"
|
||||
}
|
||||
|
||||
fn map_in_mut(mut m map[string]int) {
|
||||
if 'one' in m {
|
||||
m['one'] = 2
|
||||
}
|
||||
}
|
||||
|
||||
fn test_map_in_mut() {
|
||||
mut m := {
|
||||
'one': 1
|
||||
}
|
||||
map_in_mut(mut m)
|
||||
assert m['one'] == 2
|
||||
}
|
||||
|
||||
fn test_map_in() {
|
||||
m := {
|
||||
'Foo': 'bar'
|
||||
}
|
||||
if 'foo'.capitalize() in m {
|
||||
println('ok')
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn mut_map_with_relation_op_in_fn(mut m map[string]int) {
|
||||
if m['one'] == 1 {
|
||||
m['three'] = 3
|
||||
}
|
||||
if m['two'] != 1 {
|
||||
m['four'] = 4
|
||||
}
|
||||
if m['one'] > 0 {
|
||||
m['five'] = 5
|
||||
}
|
||||
if m['one'] < 2 {
|
||||
m['six'] = 6
|
||||
}
|
||||
if m['two'] >= 2 {
|
||||
m['seven'] = 7
|
||||
}
|
||||
if m['two'] <= 2 {
|
||||
m['eight'] = 8
|
||||
}
|
||||
}
|
||||
|
||||
fn test_mut_map_with_relation_op_in_fn() {
|
||||
mut m := {
|
||||
'one': 1
|
||||
'two': 2
|
||||
}
|
||||
mut_map_with_relation_op_in_fn(mut m)
|
||||
assert 'three' in m
|
||||
assert 'four' in m
|
||||
assert 'five' in m
|
||||
assert 'six' in m
|
||||
assert 'seven' in m
|
||||
assert 'eight' in m
|
||||
}
|
||||
|
||||
fn test_map_str_after_delete() {
|
||||
mut m := {
|
||||
'first': 1
|
||||
'second': 2
|
||||
'third': 3
|
||||
}
|
||||
osm := '${m}'
|
||||
m.delete('second')
|
||||
nsm := '${m}'
|
||||
println('m: ${m}')
|
||||
assert osm == "{'first': 1, 'second': 2, 'third': 3}"
|
||||
assert nsm == "{'first': 1, 'third': 3}"
|
||||
}
|
||||
|
||||
fn test_modify_map_value() {
|
||||
mut m1 := {
|
||||
'foo': 3
|
||||
'bar': -7
|
||||
}
|
||||
m1['foo'] += 5
|
||||
m1['bar'] *= -2
|
||||
assert m1['foo'] == 8
|
||||
assert m1['bar'] == 14
|
||||
}
|
||||
|
||||
fn test_map_clone() {
|
||||
mut nums := {
|
||||
'foo': 1
|
||||
'bar': 2
|
||||
}
|
||||
mut nums2 := nums.clone()
|
||||
nums2['foo']++
|
||||
nums2['bar'] *= 4
|
||||
assert nums['foo'] == 1
|
||||
assert nums['bar'] == 2
|
||||
assert nums2['foo'] == 2
|
||||
assert nums2['bar'] == 8
|
||||
}
|
||||
|
||||
struct MValue {
|
||||
name string
|
||||
misc map[string]string
|
||||
}
|
||||
|
||||
fn test_map_default_zero() {
|
||||
m := map[string]MValue{}
|
||||
v := m['unknown']
|
||||
x := v.misc['x']
|
||||
println(x)
|
||||
assert x == ''
|
||||
}
|
||||
|
||||
fn test_map_or() {
|
||||
m := {
|
||||
'first': 1
|
||||
'second': 2
|
||||
'third': 3
|
||||
}
|
||||
_ = m
|
||||
// num := m['first'] or { return }
|
||||
}
|
||||
|
||||
fn test_int_keys() {
|
||||
mut m := map[int]int{}
|
||||
m[3] = 9
|
||||
m[4] = 16
|
||||
assert m.len == 2
|
||||
assert m[3] == 9
|
||||
assert m[4] == 16
|
||||
m[5] += 24
|
||||
m[5]++
|
||||
assert m[5] == 25
|
||||
mut m2 := {
|
||||
3: 9
|
||||
4: 16
|
||||
5: 25
|
||||
}
|
||||
|
||||
four := 4
|
||||
m2.delete(3)
|
||||
m2.delete(four)
|
||||
m2.delete(5)
|
||||
assert m2.len == 0
|
||||
assert m2[3] == 0
|
||||
assert m2[4] == 0
|
||||
assert m2[5] == 0
|
||||
assert m2.keys() == []
|
||||
|
||||
m2 = {
|
||||
3: 9
|
||||
4: 16
|
||||
5: 25
|
||||
}
|
||||
|
||||
assert m2.len == 3
|
||||
// clone
|
||||
mc := m.clone()
|
||||
same := mc == m
|
||||
assert same
|
||||
assert mc.len == 3
|
||||
assert mc.keys() == [3, 4, 5]
|
||||
mut all := []int{}
|
||||
for k, v in mc {
|
||||
assert m[k] == v
|
||||
all << k
|
||||
all << v
|
||||
}
|
||||
assert all == [3, 9, 4, 16, 5, 25]
|
||||
|
||||
mut m3 := {
|
||||
1: 'one'
|
||||
2: 'two'
|
||||
}
|
||||
assert m3[1] == 'one'
|
||||
m3.delete(1)
|
||||
}
|
||||
|
||||
enum Color {
|
||||
red
|
||||
green
|
||||
blue
|
||||
}
|
||||
|
||||
type ColorAlias = Color
|
||||
|
||||
fn test_alias_enum() {
|
||||
mut m := map[ColorAlias]string{}
|
||||
m[Color.red] = 'hi'
|
||||
assert m[Color.red] == 'hi'
|
||||
}
|
||||
|
||||
fn test_enum_in_map() {
|
||||
mut m := map[Color]string{}
|
||||
m[Color.red] = 'hi'
|
||||
assert Color.red in m
|
||||
assert Color.green !in m
|
||||
assert Color.blue !in m
|
||||
}
|
||||
|
||||
fn test_voidptr_keys() {
|
||||
mut m := map[voidptr]string{}
|
||||
v := 5
|
||||
m[&v] = 'var'
|
||||
m[&m] = 'map'
|
||||
assert m[&v] == 'var'
|
||||
assert m[&m] == 'map'
|
||||
assert m.len == 2
|
||||
}
|
||||
|
||||
fn test_rune_keys() {
|
||||
mut m := {
|
||||
`!`: 2
|
||||
`%`: 3
|
||||
}
|
||||
assert typeof(m).name == 'map[rune]int'
|
||||
assert m[`!`] == 2
|
||||
m[`@`] = 7
|
||||
assert m.len == 3
|
||||
println(m)
|
||||
assert '${m}' == '{`!`: 2, `%`: 3, `@`: 7}'
|
||||
|
||||
/*
|
||||
mut a := []rune{}
|
||||
for k, v in m {
|
||||
a << k
|
||||
a << rune(v) + `0`
|
||||
}
|
||||
assert a == [`!`, `2`, `%`, `3`, `@`, `7`]*/
|
||||
}
|
||||
|
||||
fn test_eq() {
|
||||
a := {
|
||||
'a': 1
|
||||
'b': 2
|
||||
}
|
||||
assert a == {
|
||||
'a': 1
|
||||
'b': 2
|
||||
}
|
||||
b := {
|
||||
'a': [[1]]
|
||||
'b': [[2]]
|
||||
}
|
||||
assert b == {
|
||||
'a': [[1]]
|
||||
'b': [[2]]
|
||||
}
|
||||
c := {
|
||||
'a': {
|
||||
'11': 1
|
||||
}
|
||||
'b': {
|
||||
'22': 2
|
||||
}
|
||||
}
|
||||
assert c == {
|
||||
'a': {
|
||||
'11': 1
|
||||
}
|
||||
'b': {
|
||||
'22': 2
|
||||
}
|
||||
}
|
||||
d := {
|
||||
'a': MValue{
|
||||
name: 'aa'
|
||||
misc: {
|
||||
'11': '1'
|
||||
}
|
||||
}
|
||||
'b': MValue{
|
||||
name: 'bb'
|
||||
misc: {
|
||||
'22': '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
assert d == {
|
||||
'a': MValue{
|
||||
name: 'aa'
|
||||
misc: {
|
||||
'11': '1'
|
||||
}
|
||||
}
|
||||
'b': MValue{
|
||||
name: 'bb'
|
||||
misc: {
|
||||
'22': '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_non_string_key_map_str() {
|
||||
assert {
|
||||
23: 4
|
||||
}.str() == '{23: 4}'
|
||||
// TODO: Make runes behave the same as in ES6 for new map impl
|
||||
/*
|
||||
assert {
|
||||
`a`: 12
|
||||
`b`: 13
|
||||
}.str() == '{`a`: 12, `b`: 13}'*/
|
||||
assert {
|
||||
23: 'foo'
|
||||
25: 'bar'
|
||||
}.str() == "{23: 'foo', 25: 'bar'}"
|
||||
}
|
||||
|
||||
fn test_map_assign_empty_map_init() {
|
||||
mut a := {
|
||||
'one': 1
|
||||
}
|
||||
a = {}
|
||||
println(a)
|
||||
assert a == map[string]int{}
|
||||
assert '${a}' == '{}'
|
||||
}
|
||||
|
||||
fn test_in_map_literal() {
|
||||
assert 1 in {
|
||||
1: 'one'
|
||||
}
|
||||
}
|
||||
|
||||
fn test_in_int_keyed_map_var() {
|
||||
my_map := {
|
||||
1: 'A'
|
||||
}
|
||||
assert 1 in my_map
|
||||
assert 2 !in my_map
|
||||
}
|
||||
|
||||
fn test_byte_keys() {
|
||||
mut m := map[u8]u8{}
|
||||
byte_max := u8(255)
|
||||
for i in u8(0) .. byte_max {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in u8(0) .. 100 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == byte_max
|
||||
keys := m.keys()
|
||||
for i in u8(0) .. byte_max {
|
||||
assert keys[i] == i
|
||||
}
|
||||
for i in u8(0) .. byte_max {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_i16_keys() {
|
||||
mut m := map[i16]i16{}
|
||||
end := i16(1000)
|
||||
for i in i16(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in i16(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
keys := m.keys()
|
||||
for i in i16(0) .. end {
|
||||
assert keys[i] == i
|
||||
}
|
||||
for i in i16(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_u16_keys() {
|
||||
mut m := map[u16]u16{}
|
||||
end := u16(1000)
|
||||
for i in u16(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in u16(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
keys := m.keys()
|
||||
for i in u16(0) .. end {
|
||||
assert keys[i] == i
|
||||
}
|
||||
for i in u16(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_u32_keys() {
|
||||
mut m := map[u32]u32{}
|
||||
end := u32(1000)
|
||||
for i in u32(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in u32(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
keys := m.keys()
|
||||
for i in u32(0) .. end {
|
||||
assert keys[i] == i
|
||||
}
|
||||
for i in u32(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_int_keys2() {
|
||||
mut m := map[int]int{}
|
||||
end := 1000
|
||||
for i in int(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in int(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
keys := m.keys()
|
||||
for i in int(0) .. end {
|
||||
assert keys[i] == i
|
||||
}
|
||||
for i in int(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_i64_keys() {
|
||||
mut m := map[i64]i64{}
|
||||
end := i64(1000)
|
||||
for i in i64(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in i64(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert m.len == end
|
||||
keys := m.keys()
|
||||
for i in i64(0) .. end {
|
||||
assert keys[int(i)] == i
|
||||
}
|
||||
for i in i64(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_u64_keys() {
|
||||
mut m := map[u64]u64{}
|
||||
end := u64(1000)
|
||||
for i in u64(0) .. end {
|
||||
m[i] = i
|
||||
assert m[i] == i
|
||||
}
|
||||
for k, v in m {
|
||||
assert k == v
|
||||
}
|
||||
for i in u64(0) .. 500 {
|
||||
m[i]++
|
||||
assert m[i] == i + 1
|
||||
}
|
||||
assert u64(m.len) == end
|
||||
keys := m.keys()
|
||||
for i in u64(0) .. end {
|
||||
assert keys[int(i)] == i
|
||||
}
|
||||
for i in u64(0) .. end {
|
||||
m.delete(i)
|
||||
assert m[i] == 0
|
||||
}
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_map_set_fixed_array_variable() {
|
||||
mut m := map[string][2]f64{}
|
||||
m['A'] = [1.1, 2.2]!
|
||||
println(m)
|
||||
assert '${m}' == "{'A': [1.1, 2.2]}"
|
||||
|
||||
mut m2 := map[string][2]f64{}
|
||||
arr := [1.1, 2.2]!
|
||||
m2['A'] = arr
|
||||
println(m2)
|
||||
assert '${m2}' == "{'A': [1.1, 2.2]}"
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
module builtin
|
||||
|
||||
pub interface JS.Promise {
|
||||
then(onFullfiled JS.Any, onRejected JS.Any)
|
||||
catch(onCatch JS.Any) JS.Promise
|
||||
finally(callback JS.Any) JS.Promise
|
||||
}
|
||||
|
||||
@[use_new]
|
||||
pub fn JS.Promise.prototype.constructor(JS.Any) JS.Promise
|
||||
pub fn JS.Promise.reject(JS.Any) JS.Promise
|
||||
pub fn JS.Promise.resolve(JS.Any) JS.Promise
|
||||
pub fn JS.Promise.race(JS.Array) JS.Promise
|
||||
|
||||
// Promise represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
|
||||
pub struct Promise[T] {
|
||||
pub mut:
|
||||
promise JS.Promise @[noinit]
|
||||
}
|
||||
|
||||
pub fn promise_new[T](executor fn (resolve fn (T), reject fn (JS.Any))) Promise[T] {
|
||||
promise := JS.Promise.prototype.constructor(executor)
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn (p Promise[T]) then(on_fulfilled fn (T), on_rejected fn (JS.Any)) {
|
||||
p.promise.then(on_fulfilled, on_rejected)
|
||||
}
|
||||
|
||||
// catch returns a Promise and deals with rejected cases only.
|
||||
pub fn (p Promise[T]) catch(callback fn (error JS.Any)) Promise[T] {
|
||||
promise := p.promise.catch(callback)
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn (p Promise[T]) finally[U](callback fn ()) Promise[JS.Any] {
|
||||
promise := p.promise.finally(callback)
|
||||
return Promise[JS.Any]{promise}
|
||||
}
|
||||
|
||||
// promise_reject returns promise which was rejected because of specified error.
|
||||
pub fn promise_reject(error JS.Any) Promise[JS.Any] {
|
||||
promise := JS.Promise.reject(error)
|
||||
return Promise[JS.Any]{promise}
|
||||
}
|
||||
|
||||
// resolve returns promise which was resolved with specified value.
|
||||
pub fn promise_resolve[T](result T) Promise[T] {
|
||||
promise := JS.Promise.resolve(result)
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
// promise_race returns a promise, that fulfills or rejects, as soon as one of the promises in an iterable fulfills or rejects.
|
||||
// It returns the value or reason from that first promise.
|
||||
pub fn promise_race[T](promises []Promise[T]) Promise[T] {
|
||||
promises_ := JS.Array.prototype.constructor()
|
||||
|
||||
for elem in promises {
|
||||
promises_.push(elem.promise)
|
||||
}
|
||||
|
||||
promise := JS.Promise.race(promises_)
|
||||
return Promise[T]{promise}
|
||||
}
|
||||
|
||||
pub fn JS.Promise.all(JS.Array) JS.Promise
|
||||
pub fn JS.Promise.allSettled(JS.Array) JS.Promise
|
||||
|
||||
/*
|
||||
pub type JsAny = JS.Any
|
||||
|
||||
// all takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises.
|
||||
pub fn all(array []JS.Promise) Promise<JS.Array, js.promise.JsAny> {
|
||||
mut promise := JS.Promise(JS.Any(voidptr(0)))
|
||||
#promise = Promise.all(array.arr.arr);
|
||||
|
||||
return Promise<JS.Array,JsAny>{promise}
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,29 @@
|
||||
module builtin
|
||||
|
||||
import strings
|
||||
|
||||
pub fn (ra []rune) string() string {
|
||||
mut sb := strings.new_builder(ra.len)
|
||||
sb.write_runes(ra)
|
||||
res := sb.str()
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (c rune) repeat(count int) string {
|
||||
if count <= 0 {
|
||||
return ''
|
||||
} else if count == 1 {
|
||||
return c.str()
|
||||
}
|
||||
res := ''
|
||||
#res.str = String.fromCharCode(Number(c.val))
|
||||
|
||||
return res.repeat(count)
|
||||
}
|
||||
|
||||
pub fn (c rune) str() string {
|
||||
res := ''
|
||||
#res.str = String.fromCharCode(Number(c.val))
|
||||
|
||||
return res
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,17 @@
|
||||
module builtin
|
||||
|
||||
pub fn utf8_str_visible_length(s string) int {
|
||||
// todo: proper implementation
|
||||
res := 0
|
||||
#res.val = s.str.length;
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn utf8_str_len(s string) int {
|
||||
return s.len
|
||||
}
|
||||
|
||||
pub fn utf8_char_len(b u8) int {
|
||||
return ((0xe5000000 >> ((b >> 3) & 0x1e)) & 3) + 1
|
||||
}
|
||||
Reference in new issue
Block a user