js: fix `rand` build, properly use key values on map, add `rand.string` (#12020)
parent
60ecbec8ea
commit
82f187e5e0
|
@ -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() {
|
||||
|
|
|
@ -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 = '{'
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import rand
|
||||
|
||||
fn test_string() {
|
||||
res := rand.string(4)
|
||||
assert res.len == 4
|
||||
println(res)
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module wyrand
|
||||
|
||||
pub fn (mut r WyRandRNG) free() {}
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
@ -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) }
|
||||
}
|
|
@ -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);')
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(')
|
||||
|
|
|
@ -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('))')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue