jsgen: fix string and array for loops and improve casting (#9295)
							parent
							
								
									df46fe1373
								
							
						
					
					
						commit
						64d0006ff9
					
				|  | @ -1 +1,2 @@ | |||
| *.ppm | ||||
| *.js | ||||
|  | @ -1,6 +1,7 @@ | |||
| module builtin | ||||
| 
 | ||||
| pub struct string { | ||||
| pub: | ||||
| 	str JS.String | ||||
| 	len u32 | ||||
| } | ||||
|  |  | |||
|  | @ -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' { | ||||
|  |  | |||
|  | @ -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(')') | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue