Mercurial > projects > ddmd
diff dmd/expression/Cat.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 7427ded8caf7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/expression/Cat.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,267 @@ +module dmd.expression.Cat; + +import dmd.Type; +import dmd.Expression; +import dmd.Loc; +import dmd.TOK; +import dmd.StringExp; +import dmd.ArrayLiteralExp; +import dmd.Global; +import dmd.TY; +import dmd.Type; +import dmd.GlobalExpressions; +import dmd.ArrayTypes; +import dmd.TypeSArray; +import dmd.IntegerExp; + +import core.stdc.string; +import core.stdc.stdlib; + +import std.contracts; + +/* Also return EXP_CANT_INTERPRET if this fails + */ +Expression Cat(Type type, Expression e1, Expression e2) +{ + Expression e = EXP_CANT_INTERPRET; + Loc loc = e1.loc; + + Type t; + + Type t1 = e1.type.toBasetype(); + Type t2 = e2.type.toBasetype(); + + //printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars()); + //printf("\tt1 = %s, t2 = %s\n", t1.toChars(), t2.toChars()); + + if (e1.op == TOKnull && (e2.op == TOKint64 || e2.op == TOKstructliteral)) + { + e = e2; + goto L2; + } + else if ((e1.op == TOKint64 || e1.op == TOKstructliteral) && e2.op == TOKnull) + { + e = e1; + L2: + Type tn = e.type.toBasetype(); + if (tn.ty == Tchar || tn.ty == Twchar || tn.ty == Tdchar) + { + // Create a StringExp + size_t len = 1; + int sz = cast(int)tn.size(); + ulong v = e.toInteger(); + + char* s = cast(char*)malloc((len + 1) * sz); + memcpy(s, &v, sz); + + // Add terminating 0 + memset(s + len * sz, 0, sz); + + StringExp es = new StringExp(loc, assumeUnique(s[0..len])); + es.sz = cast(ubyte)sz; + es.committed = 1; + e = es; + } + else + { + // Create an ArrayLiteralExp + Expressions elements = new Expressions(); + elements.push(cast(void*)e); + e = new ArrayLiteralExp(e.loc, elements); + } + e.type = type; + return e; + } + else if (e1.op == TOKstring && e2.op == TOKstring) + { + // Concatenate the strings + StringExp es1 = cast(StringExp)e1; + StringExp es2 = cast(StringExp)e2; + + size_t len = es1.len + es2.len; + int sz = es1.sz; + + if (sz != es2.sz) + { + /* Can happen with: + * auto s = "foo"d ~ "bar"c; + */ + assert(global.errors); + return e; + } + + char* s = cast(char*)malloc((len + 1) * sz); + memcpy(s, es1.string_, es1.len * sz); + memcpy(s + es1.len * sz, es2.string_, es2.len * sz); + + // Add terminating 0 + memset(s + len * sz, 0, sz); + + StringExp es = new StringExp(loc, assumeUnique(s[0..len])); + es.sz = cast(ubyte)sz; + es.committed = es1.committed | es2.committed; + + Type tt; + if (es1.committed) + tt = es1.type; + else + tt = es2.type; + + es.type = type; + e = es; + } + else if (e1.op == TOKstring && e2.op == TOKint64) + { + // Concatenate the strings + StringExp es1 = cast(StringExp)e1; + size_t len = es1.len + 1; + int sz = es1.sz; + ulong v = e2.toInteger(); + + char* s = cast(char*)malloc((len + 1) * sz); + memcpy(s, es1.string_, es1.len * sz); + memcpy(s + es1.len * sz, &v, sz); + + // Add terminating 0 + memset(s + len * sz, 0, sz); + + StringExp es = new StringExp(loc, assumeUnique(s[0..len])); + es.sz = cast(ubyte)sz; + es.committed = es1.committed; + Type tt = es1.type; + es.type = type; + e = es; + } + else if (e1.op == TOKint64 && e2.op == TOKstring) + { + // Concatenate the strings + StringExp es2 = cast(StringExp)e2; + size_t len = 1 + es2.len; + int sz = es2.sz; + ulong v = e1.toInteger(); + + char* s = cast(char*)malloc((len + 1) * sz); + memcpy(s, &v, sz); + memcpy(s + sz, es2.string_, es2.len * sz); + + // Add terminating 0 + memset(s + len * sz, 0, sz); + + StringExp es = new StringExp(loc, assumeUnique(s[0..len])); + es.sz = cast(ubyte)sz; + es.committed = es2.committed; + Type tt = es2.type; + es.type = type; + e = es; + } + else if (e1.op == TOKarrayliteral && e2.op == TOKarrayliteral && + t1.nextOf().equals(t2.nextOf())) + { + // Concatenate the arrays + ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1; + ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2; + + es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy()); + es1.elements.insert(es1.elements.dim, es2.elements); + e = es1; + + if (type.toBasetype().ty == Tsarray) + { + e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es1.elements.dim, Type.tindex)); + e.type = e.type.semantic(loc, null); + } + else + e.type = type; + } + else if (e1.op == TOKarrayliteral && e2.op == TOKnull && + t1.nextOf().equals(t2.nextOf())) + { + e = e1; + goto L3; + } + else if (e1.op == TOKnull && e2.op == TOKarrayliteral && + t1.nextOf().equals(t2.nextOf())) + { + e = e2; + L3: + // Concatenate the array with null + ArrayLiteralExp es = cast(ArrayLiteralExp)e; + + es = new ArrayLiteralExp(es.loc, cast(Expressions)es.elements.copy()); + e = es; + + if (type.toBasetype().ty == Tsarray) + { + e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es.elements.dim, Type.tindex)); + e.type = e.type.semantic(loc, null); + } + else + e.type = type; + } + else if ((e1.op == TOKarrayliteral || e1.op == TOKnull) && + e1.type.toBasetype().nextOf().equals(e2.type)) + { + ArrayLiteralExp es1; + if (e1.op == TOKarrayliteral) + { es1 = cast(ArrayLiteralExp)e1; + es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy()); + es1.elements.push(cast(void*)e2); + } + else + { + es1 = new ArrayLiteralExp(e1.loc, e2); + } + e = es1; + + if (type.toBasetype().ty == Tsarray) + { + e.type = new TypeSArray(e2.type, new IntegerExp(loc, es1.elements.dim, Type.tindex)); + e.type = e.type.semantic(loc, null); + } + else + e.type = type; + } + else if (e2.op == TOKarrayliteral && + e2.type.toBasetype().nextOf().equals(e1.type)) + { + ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2; + + es2 = new ArrayLiteralExp(es2.loc, cast(Expressions)es2.elements.copy()); + es2.elements.shift(cast(void*)e1); + e = es2; + + if (type.toBasetype().ty == Tsarray) + { + e.type = new TypeSArray(e1.type, new IntegerExp(loc, es2.elements.dim, Type.tindex)); + e.type = e.type.semantic(loc, null); + } + else + e.type = type; + } + else if (e1.op == TOKnull && e2.op == TOKstring) + { + t = e1.type; + e = e2; + goto L1; + } + else if (e1.op == TOKstring && e2.op == TOKnull) + { + e = e1; + t = e2.type; + L1: + Type tb = t.toBasetype(); + if (tb.ty == Tarray && tb.nextOf().equals(e.type)) + { + Expressions expressions = new Expressions(); + expressions.push(cast(void*)e); + e = new ArrayLiteralExp(loc, expressions); + e.type = t; + } + if (!e.type.equals(type)) + { + StringExp se = cast(StringExp)e.copy(); + e = se.castTo(null, type); + } + } + return e; +} \ No newline at end of file