void WriteRegex(CiExpr[] args, int argIndex) { CiExpr pattern = args[argIndex]; if (pattern.Type.IsClass(CiSystem.RegexClass)) { pattern.Accept(this, CiPriority.Primary); } else if (pattern is CiLiteralString literal) { Write('/'); foreach (char c in literal.Value) { if (c == '/') { Write('\\'); } WriteEscapedChar(c, false); } Write('/'); WriteRegexOptions(args, "", "", "", "i", "m", "s"); } else { Write("new RegExp("); pattern.Accept(this, CiPriority.Argument); WriteRegexOptions(args, ", \"", "", "\"", "i", "m", "s"); Write(')'); } }
void MarkWritable(CiExpr target) { for (;;) { if (target is CiFieldAccess) { target = ((CiFieldAccess)target).Obj; } else if (target is CiArrayAccess) { target = ((CiArrayAccess)target).Array; } else { break; } while (target is CiCoercion) { target = (CiExpr)((CiCoercion)target).Inner; } ICiPtrType pt = target.Type as ICiPtrType; if (pt != null) { this.WritablePtrTypes.Add(pt); break; } } }
protected override int GetPriority(CiExpr expr) { if (expr is CiPropertyAccess) { CiProperty prop = ((CiPropertyAccess)expr).Property; if (prop == CiLibrary.SByteProperty) { return(4); } if (prop == CiLibrary.LowByteProperty) { return(8); } } #if !USE_INTEGER else if (expr is CiBinaryExpr) { if (((CiBinaryExpr)expr).Op == CiToken.Slash) { return(1); } } #endif return(base.GetPriority(expr)); }
static bool NeedsUnwrap(CiExpr expr) { if (expr.Type is CiArrayPtrType) { return(true); } if (!(expr.Type is CiClassPtrType)) { return(false); } if (!(expr is CiSymbolReference symbol)) { return(true); } if (symbol.Name == "this") { return(false); } if (symbol.Symbol.Parent is CiForeach forEach && forEach.Collection.Type is CiArrayType array && array.ElementType is CiClass) { return(false); } return(true); }
protected override void WriteStringLength(CiExpr expr) { this.StringLength = true; Write("strlen("); expr.Accept(this, CiPriority.Statement); Write(')'); }
protected void WriteCall(string function, CiExpr arg0) { Write(function); Write('('); arg0.Accept(this, CiPriority.Argument); Write(')'); }
void WriteClearArray(CiExpr expr) { CiArrayStorageType array = (CiArrayStorageType)expr.Type; if (array.ElementType == CiBoolType.Value) { Write("clearArray("); Write(expr); Write(", false)"); this.UsesClearMethod = true; } else if (array.ElementType == CiByteType.Value) { Write("clearByteArray("); Write(expr); Write(", "); Write(array.Length); Write(')'); this.UsesClearBytesMethod = true; } else if (array.ElementType == CiIntType.Value) { Write("clearArray("); Write(expr); Write(", 0)"); this.UsesClearMethod = true; } else { throw new ArgumentException(array.ElementType.Name); } }
protected override int GetPriority(CiExpr expr) { CiPropertyAccess pa = expr as CiPropertyAccess; if (pa != null) { if (pa.Property == CiLibrary.SByteProperty) { return(GetPriority(pa.Obj)); } if (pa.Property == CiLibrary.LowByteProperty) { return(2); } } else if (expr is CiCoercion) { CiCoercion c = (CiCoercion)expr; if (c.ResultType == CiByteType.Value && c.Inner.Type == CiIntType.Value) { return(2); } if (c.ResultType == CiIntType.Value && c.Inner.Type == CiByteType.Value) { return(8); } } return(base.GetPriority(expr)); }
void WriteNewRegExp(CiExpr[] args) { CiExpr pattern = args[1]; if (pattern is CiLiteral literal) { Write('/'); foreach (char c in (string)literal.Value) { if (c == '/') { Write('\\'); } WriteEscapedChar(c, false); } Write('/'); WriteRegexOptions(args, "", "", "", "i", "m", "s"); } else { Write("new RegExp("); pattern.Accept(this, CiPriority.Statement); WriteRegexOptions(args, ", \"", "", "\"", "i", "m", "s"); Write(')'); } }
static bool IsForeachStringStg(CiExpr expr) { return(expr is CiSymbolReference symbol && symbol.Symbol.Parent is CiForeach loop && loop.Collection.Type is CiArrayType array && array.ElementType == CiSystem.StringStorageType); }
protected static bool IsStringSubstring(CiExpr expr, out bool cast, out CiExpr ptr, out CiExpr offset, out CiExpr length) { if (expr is CiCallExpr call) { CiMethod method = (CiMethod)call.Method.Symbol; CiExpr[] args = call.Arguments; if (method == CiSystem.StringSubstring && args.Length == 2) { cast = false; ptr = call.Method.Left; offset = args[0]; length = args[1]; return(true); } if (method == CiSystem.UTF8GetString) { cast = true; ptr = args[0]; offset = args[1]; length = args[2]; return(true); } } cast = false; ptr = null; offset = null; length = null; return(false); }
CiExpr ParseParenthesized() { Expect(CiToken.LeftParenthesis); CiExpr result = ParseExpr(); Expect(CiToken.RightParenthesis); return(result); }
protected virtual void WriteContinueDoWhile(CiExpr cond) { OpenCond("if ", cond, CiPriority.Argument); WriteLine("continue"); CloseChild(); VisitXcrement <CiPostfixExpr>(cond, true); WriteLine("break"); }
protected override void WriteStaticCast(CiType type, CiExpr expr) { Write("static_cast<"); Write(type, false); Write(">("); GetStaticCastInner(type, expr).Accept(this, CiPriority.Statement); Write(')'); }
public override void Visit(CiExpr expr) { CiMethodCall call = expr as CiMethodCall; if (call != null && call.Method != null && call.Method.Throws) CheckAndThrow(call, call.Method.ErrorReturnValue); else base.Visit(expr); }
protected override void WriteStaticCast(string type, CiExpr expr) { Write("static_cast<"); Write(type); Write(">("); expr.Accept(this, CiPriority.Statement); Write(')'); }
protected override void WriteCoercedLiteral(CiType type, CiExpr literal) { literal.Accept(this, CiPriority.Argument); if (type == CiSystem.FloatType) { Write('f'); } }
protected bool OpenCond(string statement, CiExpr cond, CiPriority parent) { VisitXcrement <CiPrefixExpr>(cond, true); Write(statement); WriteExpr(cond, parent); OpenChild(); return(VisitXcrement <CiPostfixExpr>(cond, true)); }
protected override void WriteMemberOp(CiExpr left, CiSymbolReference symbol) { if (NeedsUnwrap(left)) { Write('!'); } Write('.'); }
protected override void WriteNewArray(CiType elementType, CiExpr lengthExpr, CiPriority parent) { Write("new "); if (elementType is CiNumericType numeric) { Write(GetArrayElementType(numeric)); } WriteCall("Array", lengthExpr); }
protected void WriteCall(string function, CiExpr arg0, CiExpr arg1) { Write(function); Write('('); arg0.Accept(this, CiPriority.Statement); Write(", "); arg1.Accept(this, CiPriority.Statement); Write(')'); }
void WriteCondChild(CiCondExpr condExpr, CiExpr expr) { // avoid error CS0172 if (condExpr.ResultType == CiByteType.Value && expr is CiConstExpr) { Write("(byte) "); } WriteChild(condExpr, expr); }
void OpenIndexing(CiExpr array) { array.Accept(this, CiPriority.Primary); if (array.Type is CiArrayPtrType) { Write('!'); } Write('['); }
protected override void WriteNewArray(CiType elementType, CiExpr lengthExpr, CiPriority parent) { Include("memory"); Write("std::make_shared<"); Write(elementType, false); Write("[]>("); lengthExpr.Accept(this, CiPriority.Statement); Write(')'); }
protected override void WriteEqualStringInternal(CiExpr left, CiExpr right, CiPriority parent, bool not) { this.StringEquals = true; if (not) { Write('!'); } WriteCall("CiString_Equals", left, right); }
static string GetConstString(CiExpr expr) { object o = ((CiConstExpr)expr).Value; if (o is string || o is int || o is byte) { return(Convert.ToString(o, CultureInfo.InvariantCulture)); } throw new ResolveException("Cannot convert {0} to string", expr.Type); }
protected override void WriteMemberOp(CiExpr left, CiSymbolReference symbol) { if (symbol.Symbol is CiConst) // FIXME { Write("::"); } else if (left.Type is CiClassPtrType classPtr && !IsForeachVar(left)) { Write("->"); }
protected bool IsOneAsciiString(CiExpr expr, out char c) { if (expr is CiLiteral literal && literal.Value is string s && s.Length == 1 && IsAscii(s[0])) { c = s[0]; return(true); } c = '\0'; return(false); }
public override void Visit(CiExpr statement) { VisitXcrement <CiPrefixExpr>(statement, true); if (!(statement is CiUnaryExpr unary) || (unary.Op != CiToken.Increment && unary.Op != CiToken.Decrement)) { WriteExpr(statement, CiPriority.Statement); WriteLine(); } VisitXcrement <CiPostfixExpr>(statement, true); }
void WriteUnwrappedString(CiExpr expr, CiPriority parent, bool substringOk) { if (!(expr is CiLiteral) && expr.Type == CiSystem.StringPtrType && !IsForeachStringStg(expr)) { expr.Accept(this, CiPriority.Primary); Write('!'); } else if (!substringOk && expr is CiCallExpr call && call.Method.IsReferenceTo(CiSystem.StringSubstring)) { WriteCall("String", expr); }
protected static bool IsStringEmpty(CiBinaryExpr expr, out CiExpr str) { if (expr.Left is CiSymbolReference symbol && symbol.Symbol == CiSystem.StringLength && expr.Right is CiLiteral literal && (long)literal.Value == 0) { str = symbol.Left; return(true); } str = null; return(false); }
protected override CiPriority GetPriority(CiExpr expr) { if (expr is CiPropertyAccess) { CiProperty prop = ((CiPropertyAccess) expr).Property; if (prop == CiLibrary.SByteProperty) return CiPriority.Additive; if (prop == CiLibrary.LowByteProperty) return CiPriority.And; } else if (expr is CiBinaryExpr) { if (((CiBinaryExpr) expr).Op == CiToken.Slash) return CiPriority.Postfix; } return base.GetPriority(expr); }
void ICiStatementVisitor.Visit(CiExpr statement) { Resolve((CiExpr) statement); }
protected virtual void WriteDelegateCall(CiExpr expr) { Write(expr); }
void StartFieldAccess(CiExpr expr) { WriteChild(CiPriority.Postfix, expr); if (expr.Type is CiClassPtrType) Write("->"); else Write('.'); }
bool TryWriteCallAndReturn(ICiStatement[] statements, int lastCallIndex, CiExpr returnValue) { CiMethodCall call = statements[lastCallIndex] as CiMethodCall; if (call == null || !call.Method.Throws) return false; Write(statements, lastCallIndex); Write("return "); Write(call); object errorReturnValue = call.Method.ErrorReturnValue; if (!false.Equals(errorReturnValue)) { Write(" != "); WriteConst(errorReturnValue); } if (returnValue != null) { Write(" ? "); Write(returnValue); Write(" : "); WriteConst(this.CurrentMethod.ErrorReturnValue); } WriteLine(";"); return true; }
void WriteChildWithSuggestedParentheses(CiBinaryExpr parent, CiExpr child, CiPriority suggestedParentPriority, bool assoc) { if (assoc && GetPriority(parent) == GetPriority(child)) Write(child); else WriteChild(suggestedParentPriority, child); }
void WriteCondChild(CiCondExpr condExpr, CiExpr expr) { // avoid error CS0172 if (condExpr.ResultType == CiByteType.Value && expr is CiConstExpr) Write("(byte) "); WriteChild(condExpr, expr); }
CiFieldAccess CreateFieldAccess(CiExpr obj, CiField field) { if (field.Class != this.CurrentClass && field.Visibility == CiVisibility.Private) field.Visibility = CiVisibility.Internal; if (!(obj.Type is CiClassPtrType) || ((CiClassPtrType) obj.Type).Class != field.Class) obj = Coerce(obj, new CiClassStorageType { Class = field.Class }); return new CiFieldAccess { Obj = obj, Field = field }; }
void MarkWritable(CiExpr target) { for (;;) { if (target is CiFieldAccess) target = ((CiFieldAccess) target).Obj; else if (target is CiArrayAccess) target = ((CiArrayAccess) target).Array; else break; while (target is CiCoercion) target = (CiExpr) ((CiCoercion) target).Inner; ICiPtrType pt = target.Type as ICiPtrType; if (pt != null) { this.WritablePtrTypes.Add(pt); break; } } }
CiExpr Resolve(CiExpr expr) { return expr.Accept(this); }
object ResolveConstExpr(CiExpr expr, CiType type) { expr = Coerce(Resolve(expr), type); CiConstExpr ce = expr as CiConstExpr; if (ce == null) throw new ResolveException("{0} is not constant", expr); return ce.Value; }
protected void WriteSum(CiExpr left, CiExpr right) { Write(new CiBinaryExpr { Left = left, Op = CiToken.Plus, Right = right }); }
protected virtual CiPriority GetPriority(CiExpr expr) { if (expr is CiConstExpr || expr is CiConstAccess || expr is CiVarAccess || expr is CiFieldAccess || expr is CiPropertyAccess || expr is CiArrayAccess || expr is CiMethodCall || expr is CiBinaryResourceExpr || expr is CiNewExpr) // ? return CiPriority.Postfix; if (expr is CiUnaryExpr || expr is CiCondNotExpr || expr is CiPostfixExpr) // ? return CiPriority.Prefix; if (expr is CiCoercion) return GetPriority((CiExpr) ((CiCoercion) expr).Inner); if (expr is CiBinaryExpr) { switch (((CiBinaryExpr) expr).Op) { case CiToken.Asterisk: case CiToken.Slash: case CiToken.Mod: return CiPriority.Multiplicative; case CiToken.Plus: case CiToken.Minus: return CiPriority.Additive; case CiToken.ShiftLeft: case CiToken.ShiftRight: return CiPriority.Shift; case CiToken.Less: case CiToken.LessOrEqual: case CiToken.Greater: case CiToken.GreaterOrEqual: return CiPriority.Ordering; case CiToken.Equal: case CiToken.NotEqual: return CiPriority.Equality; case CiToken.And: return CiPriority.And; case CiToken.Xor: return CiPriority.Xor; case CiToken.Or: return CiPriority.Or; case CiToken.CondAnd: return CiPriority.CondAnd; case CiToken.CondOr: return CiPriority.CondOr; default: throw new ArgumentException(((CiBinaryExpr) expr).Op.ToString()); } } if (expr is CiCondExpr) return CiPriority.CondExpr; throw new ArgumentException(expr.GetType().Name); }
protected void Write(CiExpr expr) { if (expr is CiConstExpr) WriteConst(((CiConstExpr) expr).Value); else if (expr is CiConstAccess) WriteName(((CiConstAccess) expr).Const); else if (expr is CiVarAccess) Write((CiVarAccess) expr); else if (expr is CiFieldAccess) Write((CiFieldAccess) expr); else if (expr is CiPropertyAccess) Write((CiPropertyAccess) expr); else if (expr is CiArrayAccess) Write((CiArrayAccess) expr); else if (expr is CiMethodCall) Write((CiMethodCall) expr); else if (expr is CiUnaryExpr) Write((CiUnaryExpr) expr); else if (expr is CiCondNotExpr) Write((CiCondNotExpr) expr); else if (expr is CiPostfixExpr) Write((CiPostfixExpr) expr); else if (expr is CiBinaryExpr) Write((CiBinaryExpr) expr); else if (expr is CiCondExpr) Write((CiCondExpr) expr); else if (expr is CiBinaryResourceExpr) Write((CiBinaryResourceExpr) expr); else if (expr is CiNewExpr) WriteNew(((CiNewExpr) expr).NewType); else if (expr is CiCoercion) Write((CiCoercion) expr); else throw new ArgumentException(expr.ToString()); }
protected override CiPriority GetPriority(CiExpr expr) { if (expr is CiPropertyAccess) { CiProperty prop = ((CiPropertyAccess) expr).Property; if (prop == CiLibrary.SByteProperty || prop == CiLibrary.LowByteProperty) return CiPriority.Prefix; } else if (expr is CiCoercion) { CiCoercion c = (CiCoercion) expr; if (c.ResultType == CiByteType.Value && c.Inner.Type == CiIntType.Value) return CiPriority.Prefix; } return base.GetPriority(expr); }
protected override void WriteFallthrough(CiExpr expr) { Write("goto "); if (expr != null) { Write("case "); Write(expr); } else Write("default"); WriteLine(";"); }
CiExpr Coerce(CiExpr expr, CiType expected) { return (CiExpr) Coerce((CiMaybeAssign) expr, expected); }
CiLValue ResolveLValue(CiExpr expr) { CiLValue result = Resolve(expr) as CiLValue; if (result == null) throw new ResolveException("Expected l-value"); MarkWritable(result); return result; }
static string GetConstString(CiExpr expr) { object o = ((CiConstExpr) expr).Value; if (o is string || o is int || o is byte) return Convert.ToString(o, CultureInfo.InvariantCulture); throw new ResolveException("Cannot convert {0} to string", expr.Type); }
protected void WriteNonAssocChild(CiExpr parent, CiExpr child) { WriteNonAssocChild(GetPriority(parent), child); }
static int GetConstInt(CiExpr expr) { return (int) ((CiConstExpr) expr).Value; }
void WriteClearArray(CiExpr expr) { CiArrayStorageType array = (CiArrayStorageType) expr.Type; if (array.ElementType == CiBoolType.Value) { Write("clearArray("); Write(expr); Write(", false)"); this.UsesClearMethod = true; } else if (array.ElementType == CiByteType.Value) { Write("clearByteArray("); Write(expr); Write(", "); Write(array.Length); Write(')'); this.UsesClearBytesMethod = true; } else if (array.ElementType == CiIntType.Value) { Write("clearArray("); Write(expr); Write(", 0)"); this.UsesClearMethod = true; } else throw new ArgumentException(array.ElementType.Name); }
protected override void WriteDelegateCall(CiExpr expr) { Write(expr); Write(".run"); }
protected void WriteNonAssocChild(CiPriority parentPriority, CiExpr child) { if (GetPriority(child) <= parentPriority) { Write('('); Write(child); Write(')'); } else Write(child); }
static CiType FindCommonType(CiExpr expr1, CiExpr expr2) { CiType type1 = expr1.Type; CiType type2 = expr2.Type; if (type1.Equals(type2)) return type1; if ((type1 == CiIntType.Value && type2 == CiByteType.Value) || (type1 == CiByteType.Value && type2 == CiIntType.Value)) return CiIntType.Value; CiType type = type1.Ptr; if (type != null) return type; // stg, ptr || stg, null type = type2.Ptr; if (type != null) return type; // ptr, stg || null, stg if (type1 != CiType.Null) return type1; // ptr, null if (type2 != CiType.Null) return type2; // null, ptr throw new ResolveException("Incompatible types"); }
protected override CiPriority GetPriority(CiExpr expr) { CiPropertyAccess pa = expr as CiPropertyAccess; if (pa != null) { if (pa.Property == CiLibrary.SByteProperty) return GetPriority(pa.Obj); if (pa.Property == CiLibrary.LowByteProperty) return CiPriority.Prefix; } else if (expr is CiCoercion) { CiCoercion c = (CiCoercion) expr; if (c.ResultType == CiByteType.Value && c.Inner.Type == CiIntType.Value) return CiPriority.Prefix; if (c.ResultType == CiIntType.Value && c.Inner.Type == CiByteType.Value) return CiPriority.And; } return base.GetPriority(expr); }
protected virtual void WriteFallthrough(CiExpr expr) { }
protected override void WriteFallthrough(CiExpr expr) { WriteLine("//$FALL-THROUGH$"); }
public virtual void Visit(CiExpr expr) { Write(expr); }