jsgen: fix string and array for loops and improve casting (#9295)
parent
df46fe1373
commit
64d0006ff9
|
@ -1 +1,2 @@
|
||||||
*.ppm
|
*.ppm
|
||||||
|
*.js
|
|
@ -1,6 +1,7 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
pub struct string {
|
pub struct string {
|
||||||
|
pub:
|
||||||
str JS.String
|
str JS.String
|
||||||
len u32
|
len u32
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ struct BuiltinPrototypeCongig {
|
||||||
to_string string = 'this.val.toString()'
|
to_string string = 'this.val.toString()'
|
||||||
eq string = 'this.val === other.val'
|
eq string = 'this.val === other.val'
|
||||||
extras string
|
extras string
|
||||||
|
has_strfn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ugly arguments but not sure a config struct would be worth it
|
// ugly arguments but not sure a config struct would be worth it
|
||||||
|
@ -226,7 +227,7 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeCongig) {
|
||||||
g.writeln('function ${c.typ_name}(${c.val_name} = ${c.default_value}) { ${c.constructor} }')
|
g.writeln('function ${c.typ_name}(${c.val_name} = ${c.default_value}) { ${c.constructor} }')
|
||||||
g.writeln('${c.typ_name}.prototype = {')
|
g.writeln('${c.typ_name}.prototype = {')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
g.writeln('val: ${c.default_value},')
|
g.writeln('${c.val_name}: ${c.default_value},')
|
||||||
if c.extras.len > 0 {
|
if c.extras.len > 0 {
|
||||||
g.writeln('${c.extras},')
|
g.writeln('${c.extras},')
|
||||||
}
|
}
|
||||||
|
@ -239,7 +240,7 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeCongig) {
|
||||||
g.writeln('valueOf() { return ${c.value_of} },')
|
g.writeln('valueOf() { return ${c.value_of} },')
|
||||||
g.writeln('toString() { return ${c.to_string} },')
|
g.writeln('toString() { return ${c.to_string} },')
|
||||||
g.writeln('eq(other) { return ${c.eq} },')
|
g.writeln('eq(other) { return ${c.eq} },')
|
||||||
g.writeln('str() { return new string(this.toString()) }')
|
if c.has_strfn { g.writeln('str() { return new string(this.toString()) }') }
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
g.writeln('};\n')
|
g.writeln('};\n')
|
||||||
}
|
}
|
||||||
|
@ -292,6 +293,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
value_of: 'this.str'
|
value_of: 'this.str'
|
||||||
to_string: 'this.str'
|
to_string: 'this.str'
|
||||||
eq: 'this.str === other.str'
|
eq: 'this.str === other.str'
|
||||||
|
has_strfn: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
'map' {
|
'map' {
|
||||||
|
|
|
@ -690,7 +690,9 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
|
||||||
} else {
|
} else {
|
||||||
g.write(' $op ')
|
g.write(' $op ')
|
||||||
// TODO: Multiple types??
|
// TODO: Multiple types??
|
||||||
should_cast := g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables
|
should_cast := (g.table.type_kind(stmt.left_types.first()) in shallow_equatables)
|
||||||
|
&& (g.cast_stack.len <= 0 || stmt.left_types.first() != g.cast_stack.last())
|
||||||
|
|
||||||
if should_cast {
|
if should_cast {
|
||||||
g.cast_stack << stmt.left_types.first()
|
g.cast_stack << stmt.left_types.first()
|
||||||
if g.file.mod.name == 'builtin' {
|
if g.file.mod.name == 'builtin' {
|
||||||
|
@ -920,36 +922,36 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
|
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
|
||||||
// `for num in nums {`
|
// `for num in nums {`
|
||||||
i := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
|
val := if it.val_var in ['', '_'] { '_' } else { it.val_var }
|
||||||
val := if it.val_var in ['', '_'] { '' } else { it.val_var }
|
|
||||||
// styp := g.typ(it.val_type)
|
// styp := g.typ(it.val_type)
|
||||||
g.inside_loop = true
|
if it.key_var.len > 0 {
|
||||||
g.write('for (let $i = 0; $i < ')
|
g.write('for (const [$it.key_var, $val] of ')
|
||||||
g.expr(it.cond)
|
|
||||||
g.writeln('.len; ++$i) {')
|
|
||||||
g.inside_loop = false
|
|
||||||
if val !in ['', '_'] {
|
|
||||||
g.write('\tconst $val = ')
|
|
||||||
if it.kind == .string {
|
if it.kind == .string {
|
||||||
if g.file.mod.name == 'builtin' {
|
g.write('Array.from(')
|
||||||
g.write('new ')
|
|
||||||
}
|
|
||||||
g.write('byte(')
|
|
||||||
}
|
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.write(if it.kind == .array {
|
g.write('.str.split(\'\').entries(), ([$it.key_var, $val]) => [$it.key_var, ')
|
||||||
'.arr'
|
if g.ns.name == 'builtin' { g.write('new ') }
|
||||||
} else if it.kind == .string {
|
g.write('byte($val)])')
|
||||||
'.str'
|
|
||||||
} else {
|
} else {
|
||||||
'.val'
|
g.expr(it.cond)
|
||||||
})
|
g.write('.entries()')
|
||||||
g.write('[$i]')
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g.write('for (const $val of ')
|
||||||
|
g.expr(it.cond)
|
||||||
if it.kind == .string {
|
if it.kind == .string {
|
||||||
g.write(')')
|
g.write('.str.split(\'\')')
|
||||||
}
|
}
|
||||||
g.writeln(';')
|
// cast characters to bytes
|
||||||
|
if val !in ['', '_'] && it.kind == .string {
|
||||||
|
g.write('.map(c => ')
|
||||||
|
if g.ns.name == 'builtin' { g.write('new ') }
|
||||||
|
g.write('byte(c))')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
g.writeln(') {')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
} else if it.kind == .map {
|
} else if it.kind == .map {
|
||||||
|
@ -1393,7 +1395,9 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
if l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables {
|
if l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write('.eq(')
|
g.write('.eq(')
|
||||||
|
g.cast_stack << int(l_sym.kind)
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
g.cast_stack.delete_last()
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
g.write('vEq(')
|
g.write('vEq(')
|
||||||
|
@ -1431,10 +1435,16 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
g.write(g.typ(it.right_type))
|
g.write(g.typ(it.right_type))
|
||||||
} else {
|
} else {
|
||||||
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
||||||
needs_cast := it.left_type != it.right_type
|
mut needs_cast := is_arithmetic && it.left_type != it.right_type
|
||||||
|
mut greater_typ := 0
|
||||||
|
if needs_cast {
|
||||||
|
greater_typ = g.greater_typ(it.left_type, it.right_type)
|
||||||
|
if g.cast_stack.len > 0 {
|
||||||
|
needs_cast = g.cast_stack.last() != greater_typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if is_arithmetic && needs_cast {
|
if needs_cast {
|
||||||
greater_typ := g.greater_typ(it.left_type, it.right_type)
|
|
||||||
if g.ns.name == 'builtin' {
|
if g.ns.name == 'builtin' {
|
||||||
g.write('new ')
|
g.write('new ')
|
||||||
}
|
}
|
||||||
|
@ -1445,7 +1455,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
g.write(' $it.op ')
|
g.write(' $it.op ')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
|
||||||
if is_arithmetic && needs_cast {
|
if needs_cast {
|
||||||
g.cast_stack.delete_last()
|
g.cast_stack.delete_last()
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue