js: fix `rand` build, properly use key values on map, add `rand.string` (#12020)

pull/12037/head
playX 2021-10-01 21:23:49 +03:00 committed by GitHub
parent 60ecbec8ea
commit 82f187e5e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 186 additions and 39 deletions

View File

@ -1331,8 +1331,8 @@ fn test_struct_array_of_multi_type_in() {
},
]
println(ivan in people)
println('TODO: Map eq')
// assert ivan in people
// println('TODO: Map eq')
assert ivan in people
}
fn test_struct_array_of_multi_type_index() {

View File

@ -1,7 +1,8 @@
module builtin
struct map {
m JS.Map
m JS.Map
pub:
len int
}
@ -14,7 +15,7 @@ pub fn (mut m map) delete(key voidptr) {
pub fn (m &map) free() {}
#map.prototype[Symbol.iterator] = function () { return this.map[Symbol.iterator](); }
//#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 = '{'

View File

@ -125,3 +125,16 @@ pub fn hex(len int) string {
pub fn ascii(len int) string {
return string_from_set(ascii_chars, len)
}
fn deinit() {
unsafe {
default_rng.free() // free the implementation
free(default_rng) // free the interface wrapper itself
}
}
// init initializes the default RNG.
fn init() {
default_rng = new_default()
C.atexit(deinit)
}

View File

@ -0,0 +1,17 @@
module rand
// init initializes the default RNG.
fn init() {
default_rng = new_default()
}
pub fn string(len int) string {
result := ''
#
#const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
#const charactersLength = characters.length;
#for (let i = 0;i < len.val;i++)
#result.str += characters.charAt(Math.random() * charactersLength);
return result
}

View File

@ -38,19 +38,6 @@ __global (
default_rng &PRNG
)
// init initializes the default RNG.
fn init() {
default_rng = new_default()
C.atexit(deinit)
}
fn deinit() {
unsafe {
default_rng.free() // free the implementation
free(default_rng) // free the interface wrapper itself
}
}
// new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance.
[manualfree]
pub fn new_default(config config.PRNGConfigStruct) &PRNG {

View File

@ -0,0 +1,7 @@
import rand
fn test_string() {
res := rand.string(4)
assert res.len == 4
println(res)
}

View File

@ -0,0 +1,3 @@
module wyrand
pub fn (mut r WyRandRNG) free() {}

View File

@ -250,9 +250,3 @@ pub fn (mut rng WyRandRNG) f64_in_range(min f64, max f64) f64 {
}
return min + rng.f64n(max - min)
}
// free should be called when the generator is no longer needed
[unsafe]
pub fn (mut rng WyRandRNG) free() {
unsafe { free(rng) }
}

View File

@ -0,0 +1,7 @@
module wyrand
// free should be called when the generator is no longer needed
[unsafe]
pub fn (mut rng WyRandRNG) free() {
unsafe { free(rng) }
}

View File

@ -589,9 +589,9 @@ fn (mut g JsGen) gen_str_for_map(info ast.Map, styp string, str_fn_name string)
g.definitions.writeln('\tstrings__Builder_write_string(sb, new string("{"));')
g.definitions.writeln('\tlet i = 0;')
g.definitions.writeln('\tfor (let [key,value] of m.map) {')
g.definitions.writeln('\t\tkey = new ${key_styp}(key);')
if key_sym.kind == .string {
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string(key));')
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string("\'" + key.str + "\'"));')
} else if key_sym.kind == .rune {
// tmp_str := str_intp_rune('${key_str_fn_name}(key)')
// g.definitions.writeln('\t\tstrings__Builder_write_string(sb, $tmp_str);')

View File

@ -300,11 +300,6 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeConfig) {
g.dec_indent()
g.writeln('};\n')
g.writeln('function ${c.typ_name}__eq(self,other) { return $c.eq; } ')
for method in g.method_fn_decls[c.typ_name] {
g.inside_def_typ_decl = true
g.gen_method_decl(method, .struct_method)
g.inside_def_typ_decl = false
}
}
// generate builtin type definitions, used for casting and methods.

View File

@ -294,11 +294,13 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
g.gen_deref_ptr(node.right_type)
g.write('.map.has(')
g.expr(node.left)
/*
if l_sym.sym.kind == .string {
g.write('.str')
} else {
g.write('.valueOf()')
}
}*/
g.write('.\$toJS()')
g.write(')')
} else {
g.write('.str.includes(')

View File

@ -200,6 +200,18 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
}
}
}
for mod_name in g.table.modules {
g.writeln('// Initializations for module $mod_name')
init_fn_name := '${mod_name}.init'
if initfn := g.table.find_fn(init_fn_name) {
if initfn.return_type == ast.void_type && initfn.params.len == 0 {
mod_c_name := util.no_dots(mod_name)
init_fn_c_name := '${mod_c_name}__init'
g.writeln('${init_fn_c_name}();')
}
}
}
g.write('js_main();')
g.escape_namespace()
// resolve imports
@ -207,6 +219,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
nodes := deps_resolved.nodes
mut out := g.definitions.str() + g.hashes()
// equality check for js objects
// TODO: Fix msvc bug that's preventing $embed_file('fast_deep_equal.js')
// unsafe {
@ -221,8 +234,8 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
out += 'if (typeof module === "object" && module.exports) module.exports = $export;\n'
}
out += '\n'
out += g.out.str()
out += g.out.str()
/*
TODO(playX): Again add support for these doc comments
for node in nodes {
@ -876,12 +889,18 @@ fn (mut g JsGen) expr(node ast.Expr) {
g.write(')')
}
ast.PostfixExpr {
// match node.expr {
// ast.IndexExpr {
// g.gen_postfix_index_expr(node.expr,node.op)
// } else {
g.expr(node.expr)
if node.op in [.inc, .dec] {
g.write('.val $node.op')
} else {
g.write(node.op.str())
}
// }
// }
}
ast.PrefixExpr {
if node.op in [.amp, .mul] {
@ -1126,6 +1145,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
}
}
mut array_set := false
mut map_set := false
match left {
ast.IndexExpr {
g.expr(left.left)
@ -1133,17 +1153,24 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
g.write('.valueOf()')
}
array_set = true
if g.table.get_type_symbol(left.left_type).kind == .map {
g.write('.map.set(')
map_set = true
} else {
g.write('.arr.set(')
}
g.write('new int(')
g.cast_stack << ast.int_type_idx
g.expr(left.index)
g.write('.valueOf()')
g.cast_stack.delete_last()
g.write('),')
if map_set {
g.expr(left.index)
g.write('.\$toJS(),')
} else {
g.write('new int(')
g.cast_stack << ast.int_type_idx
g.expr(left.index)
g.write('.valueOf()')
g.cast_stack.delete_last()
g.write('),')
}
}
else {
g.expr(left)
@ -2308,6 +2335,7 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
g.write(')')
} else if left_typ.kind == .map {
g.expr(expr.left)
if expr.is_setter {
g.inside_map_set = true
g.write('.map.set(')
@ -2315,7 +2343,7 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
g.write('.map.get(')
}
g.expr(expr.index)
g.write('.toString()')
g.write('.\$toJS()')
if !expr.is_setter {
g.write(')')
}
@ -2632,6 +2660,7 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
val := it.vals[i]
g.write('[')
g.expr(key)
g.write('.\$toJS()')
g.write(', ')
g.expr(val)
g.write(']')
@ -2950,3 +2979,95 @@ fn replace_op(s string) string {
else { '' }
}
}
fn (mut g JsGen) gen_postfix_index_expr(expr ast.IndexExpr, op token.Kind) {
left_typ := g.table.get_type_symbol(expr.left_type)
// TODO: Handle splice setting if it's implemented
if expr.index is ast.RangeExpr {
if left_typ.kind == .array {
g.write('array_slice(')
} else {
g.write('string_slice(')
}
g.expr(expr.left)
if expr.left_type.is_ptr() {
g.write('.valueOf()')
}
g.write(',')
if expr.index.has_low {
g.expr(expr.index.low)
} else {
g.write('new int(0)')
}
g.write(', ')
if expr.index.has_high {
g.expr(expr.index.high)
} else {
g.expr(expr.left)
if expr.left_type.is_ptr() {
g.write('.valueOf()')
}
g.write('.len')
}
g.write(')')
} else if left_typ.kind == .map {
g.expr(expr.left)
if expr.is_setter {
g.inside_map_set = true
g.write('.map.set(')
} else {
g.write('.map.get(')
}
g.expr(expr.index)
g.write('.\$toJS()')
if !expr.is_setter {
g.write(')')
} else {
g.write(',')
lsym := g.table.get_type_symbol(expr.left_type)
key_typ := match lsym.info {
ast.Map {
lsym.info.value_type
}
else {
verror('unreachable')
}
}
g.write('new ${g.typ(key_typ)}(')
g.expr(expr.left)
g.write('.map.get(')
g.expr(expr.index)
g.write('.\$toJS())')
match op {
.inc {
g.write('.val + 1)')
}
.dec {
g.write('.val - 1)')
}
else {
verror('not yet implemented')
}
}
g.write(')')
}
} else if left_typ.kind == .string {
if expr.is_setter {
// TODO: What's the best way to do this?
// 'string'[3] = `o`
} else {
// TODO: Maybe use u16 there? JS String returns values up to 2^16-1
g.write('new byte(')
g.expr(expr.left)
if expr.left_type.is_ptr() {
g.write('.valueOf()')
}
g.write('.str.charCodeAt(')
g.expr(expr.index)
g.write('))')
}
}
}