jsgen: fix string and array for loops and improve casting (#9295)

pull/9294/head
Leah Lundqvist 2021-03-14 07:20:01 +01:00 committed by GitHub
parent df46fe1373
commit 64d0006ff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 38 deletions

1
examples/.gitignore vendored
View File

@ -1 +1,2 @@
*.ppm
*.js

View File

@ -1,6 +1,7 @@
module builtin
pub struct string {
pub:
str JS.String
len u32
}

View File

@ -212,13 +212,14 @@ fn (mut g JsGen) struct_typ(s string) string {
struct BuiltinPrototypeCongig {
typ_name string
val_name string = 'val'
val_name string = 'val'
default_value string
constructor string = 'this.val = val'
value_of string = 'this.val'
to_string string = 'this.val.toString()'
eq string = 'this.val === other.val'
constructor string = 'this.val = val'
value_of string = 'this.val'
to_string string = 'this.val.toString()'
eq string = 'this.val === other.val'
extras string
has_strfn bool
}
// 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('${c.typ_name}.prototype = {')
g.inc_indent()
g.writeln('val: ${c.default_value},')
g.writeln('${c.val_name}: ${c.default_value},')
if c.extras.len > 0 {
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('toString() { return ${c.to_string} },')
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.writeln('};\n')
}
@ -292,6 +293,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
value_of: 'this.str'
to_string: 'this.str'
eq: 'this.str === other.str'
has_strfn: false
})
}
'map' {

View File

@ -690,7 +690,9 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
} else {
g.write(' $op ')
// 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 {
g.cast_stack << stmt.left_types.first()
if g.file.mod.name == 'builtin' {
@ -920,36 +922,36 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
g.writeln('}')
} else if it.kind in [.array, .string] || it.cond_type.has_flag(.variadic) {
// `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)
g.inside_loop = true
g.write('for (let $i = 0; $i < ')
g.expr(it.cond)
g.writeln('.len; ++$i) {')
g.inside_loop = false
if val !in ['', '_'] {
g.write('\tconst $val = ')
if it.key_var.len > 0 {
g.write('for (const [$it.key_var, $val] of ')
if it.kind == .string {
if g.file.mod.name == 'builtin' {
g.write('new ')
}
g.write('byte(')
}
g.expr(it.cond)
g.write(if it.kind == .array {
'.arr'
} else if it.kind == .string {
'.str'
g.write('Array.from(')
g.expr(it.cond)
g.write('.str.split(\'\').entries(), ([$it.key_var, $val]) => [$it.key_var, ')
if g.ns.name == 'builtin' { g.write('new ') }
g.write('byte($val)])')
} else {
'.val'
})
g.write('[$i]')
if it.kind == .string {
g.write(')')
g.expr(it.cond)
g.write('.entries()')
}
} else {
g.write('for (const $val of ')
g.expr(it.cond)
if it.kind == .string {
g.write('.str.split(\'\')')
}
// 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.writeln(') {')
g.stmts(it.stmts)
g.writeln('}')
} 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 {
g.expr(it.left)
g.write('.eq(')
g.cast_stack << int(l_sym.kind)
g.expr(it.right)
g.cast_stack.delete_last()
g.write(')')
} else {
g.write('vEq(')
@ -1431,10 +1435,16 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
g.write(g.typ(it.right_type))
} else {
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 {
greater_typ := g.greater_typ(it.left_type, it.right_type)
if needs_cast {
if g.ns.name == 'builtin' {
g.write('new ')
}
@ -1445,7 +1455,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
g.write(' $it.op ')
g.expr(it.right)
if is_arithmetic && needs_cast {
if needs_cast {
g.cast_stack.delete_last()
g.write(')')
}