public Statement FromSPAGS(SPAGS.Function spagsFunc, SPAGS.Statement spagsStatement, ScopedBlock jsScope) { SPAGS.Function callFunction; List<SPAGS.Expression> callParams; List<SPAGS.Expression> callVarargs; if (spagsStatement.TryGetSimpleCall(out callFunction, out callParams, out callVarargs)) { return (Statement)FromSPAGS(callFunction, callParams, callVarargs); } switch (spagsStatement.Type) { case SPAGS.StatementType.Block: SPAGS.Statement.Block spagsBlock = (SPAGS.Statement.Block)spagsStatement; Statement.GenericBlock jsBlock = new Statement.GenericBlock(); foreach (SPAGS.Statement statement in spagsBlock.ChildStatements) { jsBlock.Block.Add(FromSPAGS(spagsFunc, statement, jsScope)); } return jsBlock; case SPAGS.StatementType.Assign: SPAGS.Statement.Assign spagsAssign = (SPAGS.Statement.Assign)spagsStatement; PossibleValueTypes assignType = GetValueTypes(spagsAssign.Target.GetValueType()); Expression jsAssign = new Expression.InfixOperation( FromSPAGS(spagsAssign.Target), Infix.Assign, FromSPAGS(spagsAssign.SimpleAssignValue()).Cast(assignType)); return (Statement)jsAssign; case SPAGS.StatementType.If: SPAGS.Statement.If spagsIf = (SPAGS.Statement.If)spagsStatement; Statement.If jsIf = new Statement.If( FromSPAGS(spagsIf.IfThisIsTrue).Cast(PossibleValueTypes.Boolean)); if (spagsIf.ThenDoThis.Type == SPAGS.StatementType.Block) { SPAGS.Statement.Block thenBlock = (SPAGS.Statement.Block)spagsIf.ThenDoThis; foreach (SPAGS.Statement statement in thenBlock.ChildStatements) { jsIf.ThenDoThis.Add(FromSPAGS(spagsFunc, statement, jsScope)); } } else { jsIf.ThenDoThis.Add(FromSPAGS(spagsFunc, spagsIf.ThenDoThis, jsScope)); } if (spagsIf.ElseDoThis != null) { if (spagsIf.ElseDoThis.Type == SPAGS.StatementType.Block) { SPAGS.Statement.Block elseBlock = (SPAGS.Statement.Block)spagsIf.ElseDoThis; foreach (SPAGS.Statement statement in elseBlock.ChildStatements) { jsIf.ElseDoThis.Add(FromSPAGS(spagsFunc, statement, jsScope)); } } else { jsIf.ElseDoThis.Add(FromSPAGS(spagsFunc, spagsIf.ElseDoThis, jsScope)); } } return jsIf; case SPAGS.StatementType.Return: SPAGS.Statement.Return spagsReturn = (SPAGS.Statement.Return)spagsStatement; if (spagsReturn.Value == null) { if (spagsFunc.Signature.ReturnType.Category == SPAGS.ValueTypeCategory.Void) { return new Statement.Return(); } else { return new Statement.Return(FromSPAGS(spagsFunc.Signature.ReturnType.CreateDefaultValueExpression())); } } else { PossibleValueTypes returnType = GetValueTypes(spagsFunc.Signature.ReturnType); return new Statement.Return(FromSPAGS(spagsReturn.Value).Cast(returnType)); } case SPAGS.StatementType.VariableDeclaration: SPAGS.Statement.VariableDeclaration varDef = (SPAGS.Statement.VariableDeclaration)spagsStatement; Statement.InitVariables assignment = new Statement.InitVariables(); foreach (SPAGS.Variable variable in varDef.Variables) { Variable v; if (jsScope.Variables.ContainsKey(variable.Name)) { v = jsScope.Variables[variable.Name]; } else { v = new Variable(variable.Name, GetValueTypes(variable.Type)); jsScope.Variables.Add(variable.Name, v); } SetReference(variable, v); SPAGS.Expression val = variable.InitialValue ?? variable.Type.CreateDefaultValueExpression(); PossibleValueTypes variableType = GetValueTypes(variable.Type); if (val.IsConstant()) { v.InitialValue = FromSPAGS(val).Cast(variableType); } else { assignment.Add(v, FromSPAGS(val).Cast(variableType)); } } return assignment; case SPAGS.StatementType.While: SPAGS.Statement.While spagsLoop = (SPAGS.Statement.While)spagsStatement; Statement.While jsLoop = new Statement.While( FromSPAGS(spagsLoop.WhileThisIsTrue).Cast(PossibleValueTypes.Boolean)); if (spagsLoop.KeepDoingThis.Type == SPAGS.StatementType.Block) { SPAGS.Statement.Block body = (SPAGS.Statement.Block)spagsLoop.KeepDoingThis; foreach (SPAGS.Statement statement in body.ChildStatements) { jsLoop.KeepDoingThis.Add(FromSPAGS(spagsFunc, statement, jsScope)); } } else { jsLoop.KeepDoingThis.Add(FromSPAGS(spagsFunc, spagsLoop.KeepDoingThis, jsScope)); } return jsLoop; } return (Statement)(new Expression.Custom("(" + spagsStatement.Type + ")")); }
public Expression FromSPAGS(SPAGS.Expression spagsExpr) { SPAGS.Function callFunction; List<SPAGS.Expression> callParameters, callVarargs; if (spagsExpr.TryGetSimpleCall(out callFunction, out callParameters, out callVarargs)) { return FromSPAGS(callFunction, callParameters, callVarargs); } switch (spagsExpr.Type) { case SPAGS.ExpressionType.AllocateArray: SPAGS.Expression.AllocateArray arr = (SPAGS.Expression.AllocateArray)spagsExpr; if (arr.ElementType.Category == SPAGS.ValueTypeCategory.Struct && !((SPAGS.ValueType.Struct)arr.ElementType).IsManaged) { List<Expression> arguments = new List<Expression>(); arguments.Add(GetReference((SPAGS.ValueType.Struct)arr.ElementType)); arguments.Add(FromSPAGS(arr.Length)); return OtherLibraries.Util.structArray.Call(arguments); } else { return new FillArrayExpression( FromSPAGS(arr.ElementType.CreateDefaultValueExpression()), FromSPAGS(arr.Length)); } case SPAGS.ExpressionType.AllocStringBuffer: return new AllocateStringBufferExpression(); case SPAGS.ExpressionType.AllocStruct: SPAGS.Expression.AllocateStruct allocStruct = (SPAGS.Expression.AllocateStruct)spagsExpr; Expression structCtor = GetReference(allocStruct.TheStructType); return new Expression.New(structCtor); case SPAGS.ExpressionType.ArrayIndex: SPAGS.Expression.ArrayIndex arrayIndex = (SPAGS.Expression.ArrayIndex)spagsExpr; return FromSPAGS(arrayIndex.Target).Index(FromSPAGS(arrayIndex.Index)); case SPAGS.ExpressionType.BinaryOperator: SPAGS.Expression.BinaryOperator spagsBinOp = (SPAGS.Expression.BinaryOperator)spagsExpr; Expression left = FromSPAGS(spagsBinOp.Left); Expression right = FromSPAGS(spagsBinOp.Right); PossibleValueTypes mathCast; if (spagsBinOp.Left.GetValueType().Category == SPAGS.ValueTypeCategory.Int) { mathCast = PossibleValueTypes.Int32; } else { mathCast = PossibleValueTypes.Any; } switch (spagsBinOp.Token.Type) { case SPAGS.TokenType.Add: return left.BinOp(Infix.Add, right).Cast(mathCast); case SPAGS.TokenType.BitwiseAnd: return left.BinOp(Infix.BitwiseAnd, right); case SPAGS.TokenType.BitwiseLeftShift: return left.BinOp(Infix.BitwiseLeftShift, right); case SPAGS.TokenType.BitwiseOr: return left.BinOp(Infix.BitwiseOr, right); case SPAGS.TokenType.BitwiseRightShift: return left.BinOp(Infix.BitwiseSignedRightShift, right); case SPAGS.TokenType.BitwiseXor: return left.BinOp(Infix.BitwiseXor, right); case SPAGS.TokenType.Divide: return left.BinOp(Infix.Divide, right).Cast(mathCast); case SPAGS.TokenType.IsEqualTo: return left.BinOp(Infix.IsEqualTo, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.IsGreaterThan: return left.BinOp(Infix.IsGreaterThan, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.IsGreaterThanOrEqualTo: return left.BinOp(Infix.IsGreaterThanOrEqualTo, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.IsLessThan: return left.BinOp(Infix.IsLessThan, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.IsLessThanOrEqualTo: return left.BinOp(Infix.IsLessThanOrEqualTo, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.IsNotEqualTo: return left.BinOp(Infix.IsNotEqualTo, right).Cast(PossibleValueTypes.UInt8); case SPAGS.TokenType.LogicalAnd: return left.BinOp(Infix.LogicalAnd, right); case SPAGS.TokenType.LogicalOr: return left.BinOp(Infix.LogicalOr, right); case SPAGS.TokenType.Modulus: return left.BinOp(Infix.Modulus, right); case SPAGS.TokenType.Multiply: if (mathCast == PossibleValueTypes.Int32) { bool useSpecialFunction = true; SPAGS.ValueType leftType = spagsBinOp.Left.GetValueType(); SPAGS.ValueType rightType = spagsBinOp.Right.GetValueType(); if (leftType.IntType != "int32" || rightType.IntType != "int32" || left.ValueTypes == PossibleValueTypes.Int16 || right.ValueTypes == PossibleValueTypes.Int16 || left.ValueTypes == PossibleValueTypes.UInt8 || right.ValueTypes == PossibleValueTypes.UInt8) { useSpecialFunction = false; } else { int leftVal, rightVal; if (spagsBinOp.Left.TryGetIntValue(out leftVal) && (leftVal > -1000000) && (leftVal < 1000000)) { useSpecialFunction = false; } if (spagsBinOp.Right.TryGetIntValue(out rightVal) && (rightVal > -1000000) && (rightVal < 1000000)) { useSpecialFunction = false; } } if (useSpecialFunction) { return new MultiplyIntExpression(left, right); } else { return left.BinOp(Infix.Multiply, right).Cast(PossibleValueTypes.Int32); } } return left.BinOp(Infix.Multiply, right); case SPAGS.TokenType.Subtract: return left.BinOp(Infix.Subtract, right.Cast(mathCast)); default: throw new Exception("Unknown binop: " + spagsBinOp.Token); } case SPAGS.ExpressionType.CharLiteral: return (Expression)(int)((SPAGS.Expression.CharLiteral)spagsExpr).Value; case SPAGS.ExpressionType.Constant: return FromSPAGS(((SPAGS.Expression.Constant)spagsExpr).TheConstant.TheExpression); case SPAGS.ExpressionType.EnumValue: return (Expression)((SPAGS.Expression.EnumValue)spagsExpr).TheValue.Value; case SPAGS.ExpressionType.Field: SPAGS.Expression.Field field = (SPAGS.Expression.Field)spagsExpr; return FromSPAGS(field.Target).Index(new Expression.StringLiteral(field.TheField.Name)); case SPAGS.ExpressionType.FloatLiteral: return (Expression)((SPAGS.Expression.FloatLiteral)spagsExpr).Value; case SPAGS.ExpressionType.IntegerLiteral: return (Expression)((SPAGS.Expression.IntegerLiteral)spagsExpr).Value; case SPAGS.ExpressionType.Null: return Expression.Null; case SPAGS.ExpressionType.StringLiteral: //return new Expression.StringLiteral(((SPAGS.Expression.StringLiteral)spagsExpr).Value); return new Expression.ObfuscatedStringLiteral(((SPAGS.Expression.StringLiteral)spagsExpr).Value); case SPAGS.ExpressionType.UnaryOperator: SPAGS.Expression.UnaryOperator spagsUnOp = (SPAGS.Expression.UnaryOperator)spagsExpr; Expression operand = FromSPAGS(spagsUnOp.Operand); switch(spagsUnOp.Token.Type) { case SPAGS.TokenType.Subtract: if (spagsUnOp.Operand.GetValueType().Category == SPAGS.ValueTypeCategory.Int) { return operand.UnOp(Prefix.Negative).Cast(PossibleValueTypes.Int32); } else { return operand.UnOp(Prefix.Negative); } case SPAGS.TokenType.LogicalNot: return operand.BinOp(Infix.IsEqualTo, (Expression)0).Cast(PossibleValueTypes.UInt8); default: throw new Exception("Unknown unop: " + spagsUnOp.Token.Type); } case SPAGS.ExpressionType.Variable: SPAGS.Expression.Variable spagsVar = (SPAGS.Expression.Variable)spagsExpr; Expression expr = GetReference(spagsVar.TheVariable); // TODO: string buffers... return expr; } return new Expression.Custom("(" + spagsExpr.Type + ")"); }