Ejemplo n.º 1
0
        public override List <string> CodeGen(TranslationContext context)
        {
            var csContext  = (CSTranslationContext)context;
            var csClass    = csContext.CurrentClass;
            var codeResult = new List <string>();
            var operand    = GetOperand <VMSetToNextOperand>();

            if (operand.SearchType == VMSetToNextSearchType.ClosestHouse)
            {
                return(Line($"_bResult = false; //set to next closest house not yet impl"));
            }

            codeResult.Add($"{{ //set to next ({operand.SearchType.ToString()})");
            codeResult.Add($"var targetValue = {CSScopeMemory.GetExpression(csContext, operand.TargetOwner, operand.TargetData, false)};");

            //re-evaluation of what this actually does:
            //tries to find the next object id (from the previous) that meets a specific condition.
            //the previous object id is supplied via the target variable
            //
            //we should take the first result with object id > targetValue.

            if (operand.SearchType == VMSetToNextSearchType.PartOfAMultipartTile)
            {
                codeResult.Add($"var objPointer = context.VM.GetObjectById(targetValue);");
                codeResult.Add($"var result = VMSetToNext.MultitilePart(context, objPointer, targetValue);");
                codeResult.Add($"_bResult = result != 0;");
                codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "result", false)}");
                codeResult.Add($"}}");
            }
            else if (operand.SearchType == VMSetToNextSearchType.ObjectAdjacentToObjectInLocal)
            {
                codeResult.Add($"var objPointer = context.VM.GetObjectById(targetValue);");
                codeResult.Add($"var result = VMSetToNext.AdjToLocal(context, objPointer, {operand.Local});");
                codeResult.Add($"_bResult = result != null;");
                codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "result.ObjectID", false)}");
                codeResult.Add($"}}");
            }
            else if (operand.SearchType == VMSetToNextSearchType.Career)
            {
                codeResult.Add($"var result = Content.Content.Get().Jobs.SetToNext(targetValue);");
                codeResult.Add($"_bResult = result >= 0;");
                codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "result", false)}");
                codeResult.Add($"}}");
            }
            else if (operand.SearchType == VMSetToNextSearchType.NeighborId)
            {
                codeResult.Add($"var result = Content.Content.Get().Neighborhood.SetToNext(targetValue);");
                codeResult.Add($"_bResult = result >= 0;");
                codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "result", false)};");
                codeResult.Add($"}}");
            }
            else if (operand.SearchType == VMSetToNextSearchType.NeighborOfType)
            {
                codeResult.Add($"var result = Content.Content.Get().Neighborhood.SetToNext(targetValue, {operand.GUID});");
                codeResult.Add($"_bResult = result >= 0;");
                codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "result", false)};");
                codeResult.Add($"}}");
            }
            else
            {
                //if we've cached the search type, use that instead of all objects
                switch (operand.SearchType)
                {
                case VMSetToNextSearchType.ObjectOnSameTile:
                    codeResult.Add($"var objPointer = context.VM.GetObjectById(targetValue) ?? context.Caller;");
                    codeResult.Add($"var entities = context.VM.Context.ObjectQueries.GetObjectsAt(objPointer.Position);");
                    break;

                case VMSetToNextSearchType.Person:
                case VMSetToNextSearchType.FamilyMember:
                    codeResult.Add($"var entities = context.VM.Context.ObjectQueries.Avatars;");
                    break;

                case VMSetToNextSearchType.ObjectOfType:
                    codeResult.Add($"var entities = context.VM.Context.ObjectQueries.GetObjectsByGUID({operand.GUID});");
                    break;

                case VMSetToNextSearchType.ObjectWithCategoryEqualToSP0:
                    csClass.UseParams = true;
                    codeResult.Add($"var entities = context.VM.Context.ObjectQueries.GetObjectsByCategory(args[0]);");
                    break;

                case VMSetToNextSearchType.FSOObjectOfSemiGlobal:
                    codeResult.Add($"var semiglobal = FSO.Content.Content.Get().WorldObjects.Get(operand.GUID).Resource.SemiGlobal;");
                    codeResult.Add($"if (sg != null) {{ ");
                    codeResult.Add($"string sg_name = sg.Iff.Filename;");
                    codeResult.Add($"if (obj.SemiGlobal.Iff.Filename != null) entities = context.VM.Context.ObjectQueries.GetObjectsBySemiGlobal(sg_name);");
                    codeResult.Add($"else entities = null; }}");
                    codeResult.Add($"else entities = null;");
                    break;

                default:
                    codeResult.Add($"var entities = context.VM.Entities;");
                    break;
                }
                codeResult.Add($"_bResult = false;");
                codeResult.Add($"if (entities != null) {{");

                bool loop = (operand.SearchType == VMSetToNextSearchType.ObjectOnSameTile);

                codeResult.Add($"var ind = (entities.Count < 4)?0:VM.FindNextIndexInObjList(entities, targetValue);");
                codeResult.Add($"for (int i = ind; i < entities.Count; i++) {{");
                codeResult.Add($"var tempObj = entities[i];");

                string found = null;
                switch (operand.SearchType)
                { //manual search types
                case VMSetToNextSearchType.NonPerson:
                    found = "tempObj is VMGameObject";
                    break;

                case VMSetToNextSearchType.FamilyMember:
                    found = "(context.VM.TS1State.CurrentFamily?.FamilyGUIDs?.Contains(((VMAvatar)tempObj).Object.OBJ.GUID) ?? false)";
                    break;

                default:
                    //set to next object, or cached search.
                    break;
                }

                if (found != null)
                {
                    codeResult.Add($"if (tempObj.ObjectID > targetValue && {found}) {{");
                }
                else
                {
                    codeResult.Add($"if (tempObj.ObjectID > targetValue) {{");
                }
                codeResult.Add($"{CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "tempObj.ObjectID", false)}");
                codeResult.Add($"_bResult = true; break;");
                codeResult.Add($"}}"); //end if

                codeResult.Add($"}}"); //end loop

                if (loop)
                {
                    codeResult.Add($"if (!_bResult) {{");
                    codeResult.Add($"VMEntity first = entities.FirstOrDefault();");
                    codeResult.Add($"_bResult = first != null && entities.Contains(objPointer);");
                    codeResult.Add($"if (_bResult) {CSScopeMemory.SetStatement(csContext, operand.TargetOwner, operand.TargetData, "=", "first.ObjectID", false)}");
                    codeResult.Add($"}}");
                    //loop around
                }

                codeResult.Add($"}}");                   //end "entities != null"

                codeResult.Add($"}} //end set to next"); //end primitive scope
            }

            return(codeResult);
        }
Ejemplo n.º 2
0
        public override List <string> CodeGen(TranslationContext context)
        {
            var csContext = (CSTranslationContext)context;
            var csClass   = csContext.CurrentClass;
            var operand   = GetOperand <VMExpressionOperand>();

            var big = CSScopeMemory.IsBig(operand.LhsOwner) || CSScopeMemory.IsBig(operand.RhsOwner);

            string basicOp           = null;
            string basicExpressionOp = null;

            switch (operand.Operator)
            {
            case VMExpressionOperator.AndEquals:
                basicOp = "&="; break;

            case VMExpressionOperator.Assign:
                basicOp = "="; break;

            case VMExpressionOperator.DivEquals:
                basicOp = "/="; break;

            case VMExpressionOperator.MinusEquals:
                basicOp = "-="; break;

            case VMExpressionOperator.ModEquals:
                basicOp = "%="; break;

            case VMExpressionOperator.MulEquals:
                basicOp = "*="; break;

            case VMExpressionOperator.PlusEquals:
                basicOp = "+="; break;

            case VMExpressionOperator.TS1OrEquals:
                basicOp = "|="; break;

            case VMExpressionOperator.TS1XorEquals:
                basicOp = "^="; break;

            case VMExpressionOperator.TS1AssignSqrtRHS:
                return(Line(CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "&=",
                                                       $"(short)Math.Sqrt({CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)})", big)));

            case VMExpressionOperator.ClearFlag:
            case VMExpressionOperator.SetFlag:
                string flag;
                if (operand.RhsOwner == VMVariableScope.Literal)
                {
                    int intFlag = (1 << (operand.RhsData - 1));
                    if (operand.Operator == VMExpressionOperator.ClearFlag)
                    {
                        intFlag = ~intFlag;
                    }
                    if (big)
                    {
                        flag = intFlag.ToString();
                    }
                    else
                    {
                        flag = ((short)intFlag).ToString();
                    }
                }
                else
                {
                    if (operand.Operator == VMExpressionOperator.ClearFlag)
                    {
                        flag = $"~(1 << ({CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)} - 1))";
                    }
                    else
                    {
                        flag = $"(1 << ({CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)} - 1))";
                    }
                    if (!CSScopeMemory.IsBig(operand.LhsOwner))
                    {
                        flag = $"(short)({flag})";
                    }
                }

                if (operand.Operator == VMExpressionOperator.ClearFlag)
                {
                    return(Line(CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "&=", flag, big)));
                }
                else
                {
                    return(Line(CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "|=", flag, big)));
                }

            case VMExpressionOperator.Equals:
                basicExpressionOp = "=="; break;

            case VMExpressionOperator.GreaterThan:
                basicExpressionOp = ">"; break;

            case VMExpressionOperator.GreaterThanOrEqualTo:
                basicExpressionOp = ">="; break;

            case VMExpressionOperator.LessThan:
                basicExpressionOp = "<"; break;

            case VMExpressionOperator.LessThanOrEqualTo:
                basicExpressionOp = "<="; break;

            case VMExpressionOperator.NotEqualTo:
                basicExpressionOp = "!="; break;

            case VMExpressionOperator.IsFlagSet:
                var lExp = CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big);
                var rExp = $"(1 << ({CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)} - 1))";
                return(Line($"({lExp} & {rExp}) > 0"));

            case VMExpressionOperator.DecAndGreaterThan:
                if (CSScopeMemory.ScopeMutable(operand.LhsOwner))
                {
                    return(Line($"--{CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big)} > {CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)}"));
                }
                else
                {
                    return(new List <string>()
                    {
                        CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "-=", "1", big),
                        $"_bResult = {CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big)} > {CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)};"
                    });
                }

            case VMExpressionOperator.IncAndLessThan:
                if (CSScopeMemory.ScopeMutable(operand.LhsOwner))
                {
                    return(Line($"++{CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big)} < {CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)}"));
                }
                else
                {
                    return(new List <string>()
                    {
                        CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "+=", "1", big),
                        $"_bResult = {CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big)} < {CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big)};"
                    });
                }
            }

            if (!VM.GlobTS1)
            {
                if (operand.Operator == VMExpressionOperator.Push)
                {
                    string list;
                    switch (operand.LhsOwner)
                    {
                    case VMVariableScope.MyList:
                        list = "context.Caller.MyList"; break;

                    case VMVariableScope.StackObjectList:
                        list = "context.StackObject.MyList"; break;

                    default:
                        throw new Exception($"Invalid scope for list operation push! LHS: {operand.LhsOwner}");
                    }

                    var rhsValue = CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, false);

                    switch (operand.LhsData)
                    {
                    case 0:     //front
                        return(Line($"{list}.AddFirst({rhsValue});"));

                    case 1:     //back
                        return(Line($"{list}.AddLast({rhsValue});"));

                    case 2:
                        throw new Exception("Unknown list push destination: " + operand.LhsData);
                    }
                }
                else if (operand.Operator == VMExpressionOperator.Pop)
                {
                    string list;
                    switch (operand.RhsOwner)
                    {
                    case VMVariableScope.MyList:
                        list = "context.Caller.MyList"; break;

                    case VMVariableScope.StackObjectList:
                        list = "context.StackObject.MyList"; break;

                    default:
                        throw new Exception($"Invalid scope for list operation pop! RHS: {operand.RhsOwner}");
                    }

                    switch (operand.RhsData)
                    {
                    case 0:     //front
                        return(new List <string>()
                        {
                            "{ //list pop",
                            $"var list = {list};",
                            "_bResult = list.Count > 0;",
                            "if (_bResult) {",
                            CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "=", $"list.First.Value", false),
                            $"{list}.RemoveFirst();",
                            "}",
                            "} //end list pop"
                        });

                    case 1:     //back
                        return(new List <string>()
                        {
                            "{ //list pop",
                            $"var list = {list};",
                            "_bResult = list.Count > 0;",
                            "if (_bResult) {",
                            CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, "=", $"list.Last.Value", false),
                            $"{list}.RemoveLast();",
                            "}",
                            "} //end list pop"
                        });

                    default:
                        throw new Exception("Unknown list pop source: " + operand.LhsData);
                    }
                }
            }

            if (basicOp != null)
            {
                return(Line(CSScopeMemory.SetStatement(csContext, operand.LhsOwner, operand.LhsData, basicOp,
                                                       CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big), big)));
            }

            if (basicExpressionOp != null)
            {
                var lExp = CSScopeMemory.GetExpression(csContext, operand.LhsOwner, operand.LhsData, big);
                var rExp = CSScopeMemory.GetExpression(csContext, operand.RhsOwner, operand.RhsData, big);
                return(Line($"{lExp} {basicExpressionOp} {rExp}"));
            }

            return(Line($"//unknown expression type {operand.Operator}"));
        }
Ejemplo n.º 3
0
        private void OutputBlock(SimanticsBlock block, CSTranslationClass cls)
        {
            for (int i = 0; i < block.IBody.Count - 1; i++)
            {
                var inst = block.IBody[i];
                var body = cls.Instructions[inst.Index];
                switch (body.ReturnType)
                {
                case PrimitiveReturnType.SimanticsTrue:
                case PrimitiveReturnType.SimanticsTrueFalse:     //truefalse result discarded, same destination
                    WriteLines(body.Body, true); break;

                case PrimitiveReturnType.NativeStatementTrue:
                case PrimitiveReturnType.NativeStatementTrueFalse:     //truefalse result discarded, same destination
                    WriteLines(body.Body, false); break;

                case PrimitiveReturnType.NativeExpressionTrueFalse:
                    //we have a problem... the expression needs to evaluate, but we don't do anything with the result.
                    //put it in the boolean temp and ignore it.
                    if (body.Body.Count == 1)
                    {
                        WriteLine($"_bResult = {body.Body.First()};");
                    }
                    else
                    {
                        WriteLines(body.Body, true);
                    }
                    break;

                case PrimitiveReturnType.SimanticsSubroutine:
                //a subroutine that yields but doesn't branch.
                default:
                    throw new Exception("Non-statement in the middle of a sequence (detected areas with no branching)?");
                }
            }

            var lastInst = block.IBody[block.IBody.Count - 1];
            var lastBody = cls.Instructions[lastInst.Index];

            LastInstruction = block.LastInstructionIndex;

            string caseConst = null;

            if (block.BlockType == SimanticsBlockType.Switch ||
                block.BlockType == SimanticsBlockType.SwitchCase ||
                block.BlockType == SimanticsBlockType.SwitchLast)
            {
                caseConst = CSScopeMemory.GetConstant(Context, block.SwitchOperand.RhsOwner, block.SwitchOperand.RhsData);
            }

            switch (block.BlockType)
            {
            case SimanticsBlockType.InstructionSequence:
            case SimanticsBlockType.IfElse:
                //just set the instruction based on the value and return back to the while loop
                if (lastBody.ReturnType == PrimitiveReturnType.SimanticsSubroutine || lastInst.Yields)
                {
                    UpdateInstruction();
                    if (lastBody.Body.Count > 1)
                    {
                        WriteLines(lastBody.Body, false);
                        WriteLine($"return _sResult;");
                    }
                    else
                    {
                        WriteLine($"return {lastBody.Body.First()};");
                    }
                    break;
                }

                switch (lastBody.ReturnType)
                {
                case PrimitiveReturnType.NativeStatementTrueFalse:
                    if (lastInst.Instruction.TruePointer == lastInst.Instruction.FalsePointer)
                    {
                        goto case PrimitiveReturnType.NativeStatementTrue;
                    }
                    WriteLines(lastBody.Body, false);
                    WriteLine("if (_bResult) ");
                    OutputBinaryBranch(lastInst.Instruction, cls);
                    break;

                case PrimitiveReturnType.NativeExpressionTrueFalse:
                    if (lastInst.Instruction.TruePointer == lastInst.Instruction.FalsePointer)
                    {
                        WriteLine($"_bResult = {lastBody.Body.First()}; //true and false do the same thing");
                        OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    }
                    else
                    {
                        WriteLine($"if ({lastBody.Body.First()}) ");
                        OutputBinaryBranch(lastInst.Instruction, cls);
                    }
                    break;

                case PrimitiveReturnType.SimanticsTrueFalse:
                    if (lastInst.Instruction.TruePointer == lastInst.Instruction.FalsePointer)
                    {
                        goto case PrimitiveReturnType.SimanticsTrue;
                    }
                    WriteLine($"if ({lastBody.Body.First()} == VMPrimitiveExitCode.GOTO_TRUE) ");
                    OutputBinaryBranch(lastInst.Instruction, cls);
                    break;

                case PrimitiveReturnType.SimanticsStatement:
                    if (lastInst.Instruction.TruePointer == lastInst.Instruction.FalsePointer)
                    {
                        WriteLines(lastBody.Body, false);
                        OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    }
                    else
                    {
                        WriteLines(lastBody.Body, false);
                        WriteLine($"if (_sResult == VMPrimitiveExitCode.GOTO_TRUE) ");
                        OutputBinaryBranch(lastInst.Instruction, cls);
                    }
                    break;

                case PrimitiveReturnType.NativeStatementTrue:
                    WriteLines(lastBody.Body, false);
                    OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    break;

                case PrimitiveReturnType.SimanticsTrue:
                    WriteLines(lastBody.Body, true);
                    OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    break;
                }

                if (block.Parent == cls.Structure.RootBlock && cls.HasGlobalSwitch)
                {
                    WriteLine("break;");
                }
                break;

            case SimanticsBlockType.Switch:
                string switchLhs = CSScopeMemory.GetExpression(Context, block.SwitchOperand.LhsOwner, block.SwitchOperand.LhsData, true);
                WriteLine($"switch ({switchLhs}) ");
                WriteLine("{");
                IndentLevel++;
                WriteLine($"case {caseConst}:");
                IndentLevel++;
                var set = new HashSet <string> {
                    caseConst
                };
                cls.SwitchPreviousCases[block] = set;
                OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                WriteLine($"break;");
                IndentLevel--;
                OutputReturnBlockOrJump(lastInst.Instruction.FalsePointer, cls);
                break;

            case SimanticsBlockType.SwitchCase:
                var cset = cls.SwitchPreviousCases[FindSwitchBlockStart(block)];

                if (cset.Contains(caseConst))
                {
                    WriteLine($"// case {caseConst} duplicated! skipped block at {lastInst.Instruction.FalsePointer}");
                }
                else
                {
                    cset.Add(caseConst);
                    WriteLine($"case {caseConst}:");
                    IndentLevel++;
                    OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    WriteLine($"break;");
                    IndentLevel--;
                }
                OutputReturnBlockOrJump(lastInst.Instruction.FalsePointer, cls);
                break;

            case SimanticsBlockType.SwitchLast:
                var lset = cls.SwitchPreviousCases[FindSwitchBlockStart(block)];

                if (lset.Contains(caseConst))
                {
                    WriteLine($"// case {caseConst} duplicated! skipped block at {lastInst.Instruction.FalsePointer}");
                }
                else
                {
                    lset.Add(caseConst);
                    WriteLine($"case {caseConst}:");
                    IndentLevel++;
                    OutputReturnBlockOrJump(lastInst.Instruction.TruePointer, cls);
                    WriteLine($"break;");
                    IndentLevel--;
                }
                WriteLine($"default:");
                IndentLevel++;
                OutputReturnBlockOrJump(lastInst.Instruction.FalsePointer, cls);
                WriteLine($"break;");
                IndentLevel--;
                IndentLevel--;
                WriteLine("}");
                if (FindSwitchBlockStart(block).Parent == cls.Structure.RootBlock && cls.HasGlobalSwitch)
                {
                    WriteLine("break;");
                }
                break;

            default:
                throw new Exception($"Block type {block.BlockType.ToString()} not yet implemented.");
            }
            //our last instruction
        }