cgen: in [] optimization

pull/4077/head
Alexander Medvednikov 2020-03-19 16:12:46 +01:00
parent 010f3efcf0
commit b7a036945d
5 changed files with 45 additions and 1 deletions

View File

@ -42,7 +42,7 @@ pub fn parse_rfc2822(s string) ?Time {
mm := pos / 3 + 1
mut tmstr := byteptr(0)
unsafe { tmstr = malloc(s.len * 2) }
count := C.sprintf(charptr(tmstr), '%s-%02d-%s %s'.str, fields[3].str, mm,
count := C.sprintf(charptr(tmstr), '%s-%02d-%s %s', fields[3].str, mm,
fields[1].str, fields[4].str)
t := parse(tos(tmstr, count)) or {

View File

@ -944,6 +944,16 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
else if node.op == .key_in {
right_sym := g.table.get_type_symbol(node.right_type)
if right_sym.kind == .array {
match node.right {
ast.ArrayInit {
// `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3`
// avoids an allocation
// g.write('/*in opt*/')
g.in_optimization(node.left, it)
return
}
else {}
}
styp := g.typ(node.left_type)
g.write('_IN($styp, ')
g.expr(node.left)
@ -1634,6 +1644,30 @@ fn (g mut Gen) gen_filter(node ast.MethodCallExpr) {
g.write(tmp)
}
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
fn (g mut Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
is_str := right.elem_type == table.string_type
for i, array_expr in right.exprs {
if is_str {
g.write('string_eq(')
}
g.expr(left)
if is_str {
g.write(', ')
}
else {
g.write(' == ')
}
g.expr(array_expr)
if is_str {
g.write(')')
}
if i < right.exprs.len - 1 {
g.write(' || ')
}
}
}
fn op_to_fn_name(name string) string {
return match name {
'+'{

View File

@ -40,6 +40,8 @@ const (
#endif
#endif
#define V_COMMIT_HASH "TODO"
'
c_headers = '

View File

@ -33,6 +33,10 @@ void User_foo(User* u) {
array_string zzz = array_repeat(new_array_from_c_array(1, 1, sizeof(string), (string[]){
tos3(""),
}), u->age);
int a = 10;
if (a == 10 || a == 20 || a == 30) {
int b = 10;
}
}
void println(string s) {

View File

@ -26,6 +26,10 @@ fn get_user_opt() ?User {
fn (u &User) foo() {
age := u.age
zzz := [''].repeat(u.age)
a := 10
if a in [10, 20, 30] {
b := 10
}
}
fn println(s string) {}