Exemplo n.º 1
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, BooleanCombination boolComb, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new ParserException(boolComb, "Cannot have this expression here.");
            }

            ByteBuffer rightBuffer = new ByteBuffer();

            Expression[] expressions = boolComb.Expressions;
            bcc.CompileExpression(parser, rightBuffer, expressions[expressions.Length - 1], true);
            for (int i = expressions.Length - 2; i >= 0; --i)
            {
                ByteBuffer leftBuffer = new ByteBuffer();
                bcc.CompileExpression(parser, leftBuffer, expressions[i], true);
                Token op = boolComb.Ops[i];
                if (op.Value == "&&")
                {
                    leftBuffer.Add(op, OpCode.JUMP_IF_FALSE_NO_POP, rightBuffer.Size);
                }
                else
                {
                    leftBuffer.Add(op, OpCode.JUMP_IF_TRUE_NO_POP, rightBuffer.Size);
                }
                leftBuffer.Concat(rightBuffer);
                rightBuffer = leftBuffer;
            }

            buffer.Concat(rightBuffer);
        }
Exemplo n.º 2
0
 public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, BracketIndex bracketIndex, bool outputUsed)
 {
     if (!outputUsed)
     {
         throw new ParserException(bracketIndex, "This expression does nothing.");
     }
     bcc.CompileExpression(parser, buffer, bracketIndex.Root, true);
     bcc.CompileExpression(parser, buffer, bracketIndex.Index, true);
     buffer.Add(bracketIndex.BracketToken, OpCode.INDEX);
 }
Exemplo n.º 3
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, NullCoalescer nullCoalescer, bool outputUsed)
        {
            ByteCodeCompiler.EnsureUsed(nullCoalescer, outputUsed);

            bcc.CompileExpression(parser, buffer, nullCoalescer.PrimaryExpression, true);
            ByteBuffer secondaryExpression = new ByteBuffer();

            bcc.CompileExpression(parser, secondaryExpression, nullCoalescer.SecondaryExpression, true);
            buffer.Add(nullCoalescer.FirstToken, OpCode.POP_IF_NULL_OR_JUMP, secondaryExpression.Size);
            buffer.Concat(secondaryExpression);
        }
        public static void Compile(
            ByteCodeCompiler bcc,
            ParserContext parser,
            ByteBuffer buffer,
            CoreFunctionInvocation coreFuncInvocation,
            Expression[] argsOverrideOrNull,
            Token tokenOverrideOrNull,
            bool outputUsed)
        {
            Token token = tokenOverrideOrNull ?? coreFuncInvocation.FirstToken;

            Expression[] args = argsOverrideOrNull ?? coreFuncInvocation.Args;

            if (coreFuncInvocation.FunctionId == (int)CoreFunctionID.TYPE_IS)
            {
                ByteCodeCompiler.EnsureUsed(coreFuncInvocation, outputUsed);

                bcc.CompileExpression(parser, buffer, args[0], true);
                int   typeCount  = args.Length - 1;
                int[] actualArgs = new int[typeCount + 3];
                actualArgs[0] = coreFuncInvocation.FunctionId;
                actualArgs[1] = 1; // output used
                actualArgs[2] = typeCount;
                for (int i = typeCount - 1; i >= 0; --i)
                {
                    IntegerConstant typeArg = args[args.Length - 1 - i] as IntegerConstant;
                    if (typeArg == null)
                    {
                        throw new ParserException(coreFuncInvocation, "typeis requires type enum values.");
                    }
                    actualArgs[3 + i] = typeArg.Value + 1;
                }
                buffer.Add(token, OpCode.CORE_FUNCTION, actualArgs);
                return;
            }

            foreach (Expression arg in args)
            {
                bcc.CompileExpression(parser, buffer, arg, true);
            }

            if (coreFuncInvocation.FunctionId == (int)CoreFunctionID.INT_QUEUE_WRITE_16)
            {
                buffer.Add(token, OpCode.CORE_FUNCTION, coreFuncInvocation.FunctionId, outputUsed ? 1 : 0, args.Length - 1);
                return;
            }

            buffer.Add(token, OpCode.CORE_FUNCTION, coreFuncInvocation.FunctionId, outputUsed ? 1 : 0);
        }
Exemplo n.º 5
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ForEachLoop forEachLoop)
        {
            bcc.CompileExpression(parser, buffer, forEachLoop.IterationExpression, true);
            buffer.Add(
                forEachLoop.IterationExpression.FirstToken,
                OpCode.VERIFY_TYPE_IS_ITERABLE,
                forEachLoop.ListLocalId.ID,
                forEachLoop.IndexLocalId.ID);

            ByteBuffer body  = new ByteBuffer();
            ByteBuffer body2 = new ByteBuffer();

            bcc.Compile(parser, body2, forEachLoop.Code);

            body.Add(
                forEachLoop.FirstToken,
                OpCode.ITERATION_STEP,
                body2.Size + 1,
                forEachLoop.IterationVariableId.ID,
                forEachLoop.IndexLocalId.ID,
                forEachLoop.ListLocalId.ID);

            body2.Add(null, OpCode.JUMP, -body2.Size - 2);
            body.Concat(body2);

            body.ResolveBreaks();
            body.ResolveContinues();

            buffer.Concat(body);
        }
Exemplo n.º 6
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Ternary ternary, bool outputUsed)
        {
            ByteCodeCompiler.EnsureUsed(ternary, outputUsed);

            bcc.CompileExpression(parser, buffer, ternary.Condition, true);
            ByteBuffer trueBuffer = new ByteBuffer();

            bcc.CompileExpression(parser, trueBuffer, ternary.TrueValue, true);
            ByteBuffer falseBuffer = new ByteBuffer();

            bcc.CompileExpression(parser, falseBuffer, ternary.FalseValue, true);
            trueBuffer.Add(null, OpCode.JUMP, falseBuffer.Size);
            buffer.Add(ternary.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueBuffer.Size);
            buffer.Concat(trueBuffer);
            buffer.Concat(falseBuffer);
        }
Exemplo n.º 7
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, IfStatement ifStatement)
        {
            bcc.CompileExpression(parser, buffer, ifStatement.Condition, true);
            ByteBuffer trueCode = new ByteBuffer();

            bcc.Compile(parser, trueCode, ifStatement.TrueCode);
            ByteBuffer falseCode = new ByteBuffer();

            bcc.Compile(parser, falseCode, ifStatement.FalseCode);

            if (falseCode.Size == 0)
            {
                if (trueCode.Size == 0)
                {
                    buffer.Add(ifStatement.Condition.FirstToken, OpCode.POP);
                }
                else
                {
                    buffer.Add(ifStatement.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueCode.Size);
                    buffer.Concat(trueCode);
                }
            }
            else
            {
                trueCode.Add(null, OpCode.JUMP, falseCode.Size);
                buffer.Add(ifStatement.Condition.FirstToken, OpCode.JUMP_IF_FALSE, trueCode.Size);
                buffer.Concat(trueCode);
                buffer.Concat(falseCode);
            }
        }
Exemplo n.º 8
0
 public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, NegativeSign negativeSign, bool outputUsed)
 {
     if (!outputUsed)
     {
         throw new ParserException(negativeSign, "This expression does nothing.");
     }
     bcc.CompileExpression(parser, buffer, negativeSign.Root, true);
     buffer.Add(negativeSign.FirstToken, OpCode.NEGATIVE_SIGN);
 }
Exemplo n.º 9
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, BooleanNot boolNot, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new ParserException(boolNot, "Cannot have this expression here.");
            }

            bcc.CompileExpression(parser, buffer, boolNot.Root, true);
            buffer.Add(boolNot.FirstToken, OpCode.BOOLEAN_NOT);
        }
Exemplo n.º 10
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ListSlice listSlice, bool outputUsed)
        {
            ByteCodeCompiler.EnsureUsed(listSlice, outputUsed);
            bcc.CompileExpression(parser, buffer, listSlice.Root, true);

            Expression step    = listSlice.Items[2];
            bool       isStep1 = step is IntegerConstant && ((IntegerConstant)step).Value == 1;

            int serializeThese = isStep1 ? 2 : 3;

            for (int i = 0; i < serializeThese; ++i)
            {
                Expression item = listSlice.Items[i];
                if (item != null)
                {
                    bcc.CompileExpression(parser, buffer, item, true);
                }
            }

            bool firstIsPresent  = listSlice.Items[0] != null;
            bool secondIsPresent = listSlice.Items[1] != null;

            buffer.Add(listSlice.BracketToken, OpCode.LIST_SLICE, new int[] { firstIsPresent ? 1 : 0, secondIsPresent ? 1 : 0, isStep1 ? 0 : 1 });
        }
Exemplo n.º 11
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, DoWhileLoop doWhileLoop)
        {
            ByteBuffer loopBody = new ByteBuffer();

            bcc.Compile(parser, loopBody, doWhileLoop.Code);
            loopBody.ResolveContinues(true); // continues should jump to the condition, hence the true.

            ByteBuffer condition = new ByteBuffer();

            bcc.CompileExpression(parser, condition, doWhileLoop.Condition, true);
            loopBody.Concat(condition);
            loopBody.Add(doWhileLoop.Condition.FirstToken, OpCode.JUMP_IF_TRUE, -loopBody.Size - 1);
            loopBody.ResolveBreaks();

            buffer.Concat(loopBody);
        }
Exemplo n.º 12
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ListDefinition listDef, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new ParserException(listDef, "List allocation made without storing it. This is likely a mistake.");
            }
            foreach (Expression item in listDef.Items)
            {
                bcc.CompileExpression(parser, buffer, item, true);
            }
            List <int> args = new List <int>()
            {
                listDef.Items.Length
            };

            listDef.ResolvedType.ListItemType.BuildEncoding(args);
            buffer.Add(listDef.FirstToken, OpCode.DEF_LIST, args.ToArray());
        }
Exemplo n.º 13
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, WhileLoop whileLoop)
        {
            ByteBuffer loopBody = new ByteBuffer();

            bcc.Compile(parser, loopBody, whileLoop.Code);
            ByteBuffer condition = new ByteBuffer();

            bcc.CompileExpression(parser, condition, whileLoop.Condition, true);

            condition.Add(whileLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, loopBody.Size + 1);
            condition.Concat(loopBody);
            condition.Add(null, OpCode.JUMP, -condition.Size - 1);

            condition.ResolveBreaks();
            condition.ResolveContinues();

            buffer.Concat(condition);
        }
Exemplo n.º 14
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Cast castExpression, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new ParserException(castExpression, "The output of a cast must be used.");
            }

            // This should have been filtered out before now.
            if (castExpression.Expression.ResolvedType == castExpression.ResolvedType)
            {
                throw new Exception();
            }

            bcc.CompileExpression(parser, buffer, castExpression.Expression, true);

            List <int> args = new List <int>();

            EncodeTypeInfoToIntBuffer(args, castExpression.ResolvedType, castExpression.DoIntFloatConversions);
            buffer.Add(castExpression.FirstToken, OpCode.CAST, args.ToArray());
        }
Exemplo n.º 15
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ReturnStatement returnStatement)
        {
            if (returnStatement.Owner is ConstructorDefinition)
            {
                if (returnStatement.Expression != null)
                {
                    throw new ParserException(returnStatement, "Cannot return a value from a constructor.");
                }
            }

            if (returnStatement.Expression == null || returnStatement.Expression is NullConstant)
            {
                buffer.Add(returnStatement.FirstToken, OpCode.RETURN, 0);
            }
            else
            {
                bcc.CompileExpression(parser, buffer, returnStatement.Expression, true);
                buffer.Add(returnStatement.FirstToken, OpCode.RETURN, 1);
            }
        }
Exemplo n.º 16
0
        public static void Compile(
            ByteCodeCompiler bcc,
            ParserContext parser,
            ByteBuffer buffer,
            CniFunctionInvocation cniFuncInvocation,
            Expression[] argsOverrideOrNull,
            Token throwTokenOverrideOrNull,
            bool outputUsed)
        {
            CniFunction cniFunc = cniFuncInvocation.CniFunction;

            Expression[] args = argsOverrideOrNull ?? cniFuncInvocation.Args;
            foreach (Expression arg in args)
            {
                bcc.CompileExpression(parser, buffer, arg, true);
            }
            Token throwToken = throwTokenOverrideOrNull ?? cniFuncInvocation.FirstToken;

            buffer.Add(throwToken, OpCode.CNI_INVOKE, cniFunc.ID, cniFunc.ArgCount, outputUsed ? 1 : 0);
        }
Exemplo n.º 17
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ForLoop forLoop)
        {
            bcc.Compile(parser, buffer, forLoop.Init);

            ByteBuffer codeBuffer = new ByteBuffer();

            bcc.Compile(parser, codeBuffer, forLoop.Code);
            codeBuffer.ResolveContinues(true); // resolve continues as jump-to-end before you add the step instructions.
            bcc.Compile(parser, codeBuffer, forLoop.Step);

            ByteBuffer forBuffer = new ByteBuffer();

            bcc.CompileExpression(parser, forBuffer, forLoop.Condition, true);
            forBuffer.Add(forLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, codeBuffer.Size + 1); // +1 to go past the jump I'm about to add.

            forBuffer.Concat(codeBuffer);
            forBuffer.Add(null, OpCode.JUMP, -forBuffer.Size - 1);

            forBuffer.ResolveBreaks();

            buffer.Concat(forBuffer);
        }
Exemplo n.º 18
0
        private static void CompileImpl(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Expression root, Token dotToken, Token fieldToken, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new ParserException(root.FirstToken, "This expression does nothing.");
            }
            bcc.CompileExpression(parser, buffer, root, true);
            int             rawNameId          = parser.GetId(fieldToken.Value);
            int             localeId           = parser.GetLocaleId(root.Owner.FileScope.CompilationScope.Locale);
            int             localeScopedNameId = rawNameId * parser.GetLocaleCount() + localeId;
            ClassDefinition cd      = root.ClassOwner;
            int             classId = cd == null ? -1 : cd.ClassID;

            buffer.Add(
                dotToken,
                OpCode.DEREF_DOT,
                rawNameId,
                localeScopedNameId,
                classId,
                root.CompilationScope.ScopeNumId,
                -1, 0);
        }
Exemplo n.º 19
0
        // Shared code for functions/constructors/lambdas
        internal static void CompileFunctionArgs(
            ByteCodeCompiler bcc,
            ParserContext parser,
            ByteBuffer buffer,
            IList <Token> argNames,
            IList <Expression> argValues,
            List <int> offsetsForOptionalArgs,
            VariableId[] variableIds)
        {
            int bufferStartSize = buffer.Size;

            for (int i = 0; i < argNames.Count; ++i)
            {
                if (argValues[i] != null)
                {
                    bcc.CompileExpression(parser, buffer, argValues[i], true);
                    buffer.Add(argNames[i], OpCode.ASSIGN_LOCAL, i);
                    offsetsForOptionalArgs.Add(buffer.Size - bufferStartSize);
                }
            }

            // Arguments that are actually closure variables and not plain locals need to be converted.
            for (int i = 0; i < argValues.Count; ++i)
            {
                VariableId varId = variableIds[i];
                if (varId.UsedByClosure)
                {
                    // It's simple to copy all passed args at function invocation time to locals, which, on
                    // its own, is incorrect. Therefore add bytecode that will dereference those local ID's and
                    // assign them to the proper closure ID. This eliminates the need to make a dinstinction in
                    // CALL_FUNCTION between local and closure args.
                    buffer.Add(null, OpCode.LOCAL, i);
                    buffer.Add(null, OpCode.ASSIGN_CLOSURE, varId.ClosureID);
                }
            }
        }
Exemplo n.º 20
0
 public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, ThrowStatement throwStatement)
 {
     bcc.CompileExpression(parser, buffer, throwStatement.Expression, true);
     buffer.Add(throwStatement.FirstToken, OpCode.THROW);
 }
Exemplo n.º 21
0
 public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, IsComparison isComp, bool outputUsed)
 {
     ByteCodeCompiler.EnsureUsed(isComp.IsToken, outputUsed);
     bcc.CompileExpression(parser, buffer, isComp.Expression, true);
     buffer.Add(isComp.IsToken, OpCode.IS_COMPARISON, isComp.ClassDefinition.ClassID);
 }
Exemplo n.º 22
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, FunctionCall funCall, bool outputUsed)
        {
            bool argCountIsNegativeOne       = false;
            FunctionDefinition ownerFunction = funCall.Owner as FunctionDefinition;

            if (ownerFunction != null &&
                ownerFunction.NameToken.Value == "_LIB_CORE_invoke" &&
                ownerFunction.FileScope.CompilationScope.Dependencies.Length == 0)
            {
                argCountIsNegativeOne = true;
            }

            Expression root = funCall.Root;

            if (root is FunctionReference)
            {
                FunctionReference  verifiedFunction = (FunctionReference)root;
                FunctionDefinition fd = verifiedFunction.FunctionDefinition;

                if (parser.InlinableLibraryFunctions.Contains(fd))
                {
                    CompileInlinedLibraryFunctionCall(bcc, parser, buffer, funCall, fd, outputUsed);
                }
                else
                {
                    bcc.CompileExpressionList(parser, buffer, funCall.Args, true);
                    if (fd.Owner is ClassDefinition)
                    {
                        ClassDefinition cd = (ClassDefinition)fd.Owner;
                        if (fd.Modifiers.HasStatic)
                        {
                            buffer.Add(
                                funCall.ParenToken,
                                OpCode.CALL_FUNCTION,
                                (int)FunctionInvocationType.STATIC_METHOD,
                                funCall.Args.Length,
                                fd.FunctionID,
                                outputUsed ? 1 : 0,
                                cd.ClassID);
                        }
                        else
                        {
                            buffer.Add(
                                funCall.ParenToken,
                                OpCode.CALL_FUNCTION,
                                (int)FunctionInvocationType.LOCAL_METHOD,
                                funCall.Args.Length,
                                fd.FunctionID,
                                outputUsed ? 1 : 0,
                                cd.ClassID,
                                verifiedFunction.FunctionDefinition.MemberID);
                        }
                    }
                    else
                    {
                        // vanilla function
                        buffer.Add(
                            funCall.ParenToken,
                            OpCode.CALL_FUNCTION,
                            (int)FunctionInvocationType.NORMAL_FUNCTION,
                            funCall.Args.Length,
                            fd.FunctionID,
                            outputUsed ? 1 : 0,
                            0);
                    }
                }
            }
            else if (root is DotField)
            {
                DotField   ds           = (DotField)root;
                Expression dotRoot      = ds.Root;
                int        globalNameId = parser.GetId(ds.FieldToken.Value);
                bcc.CompileExpression(parser, buffer, dotRoot, true);
                bcc.CompileExpressionList(parser, buffer, funCall.Args, true);
                int localeId = parser.GetLocaleId(ds.Owner.FileScope.CompilationScope.Locale);
                buffer.Add(
                    funCall.ParenToken,
                    OpCode.CALL_FUNCTION,
                    (int)FunctionInvocationType.FIELD_INVOCATION,
                    funCall.Args.Length,
                    0,
                    outputUsed ? 1 : 0,
                    globalNameId,
                    localeId);
            }
            else if (root is BaseMethodReference)
            {
                BaseMethodReference bmr = (BaseMethodReference)root;
                FunctionDefinition  fd  = bmr.ClassToWhichThisMethodRefers.GetMethod(bmr.FieldToken.Value, true);
                if (fd == null)
                {
                    throw new ParserException(bmr.DotToken, "This method does not exist on any base class.");
                }

                bcc.CompileExpressionList(parser, buffer, funCall.Args, true);
                buffer.Add(
                    funCall.ParenToken,
                    OpCode.CALL_FUNCTION,
                    (int)FunctionInvocationType.LOCAL_METHOD,
                    funCall.Args.Length,
                    fd.FunctionID,
                    outputUsed ? 1 : 0,
                    bmr.ClassToWhichThisMethodRefers.ClassID,
                    -1);
            }
            else
            {
                bcc.CompileExpression(parser, buffer, root, true);
                bcc.CompileExpressionList(parser, buffer, funCall.Args, true);
                buffer.Add(
                    funCall.ParenToken,
                    OpCode.CALL_FUNCTION,
                    (int)FunctionInvocationType.POINTER_PROVIDED,
                    argCountIsNegativeOne ? -1 : funCall.Args.Length,
                    0,
                    outputUsed ? 1 : 0,
                    0);
            }
        }
Exemplo n.º 23
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, SwitchStatement switchStatement)
        {
            bool isInt = switchStatement.UsesIntegers;

            bcc.CompileExpression(parser, buffer, switchStatement.Condition, true);

            ByteBuffer chunkBuffer = new ByteBuffer();

            Dictionary <int, int>    chunkIdsToOffsets  = new Dictionary <int, int>();
            Dictionary <int, int>    integersToChunkIds = new Dictionary <int, int>();
            Dictionary <string, int> stringsToChunkIds  = new Dictionary <string, int>();

            int defaultChunkId = -1;

            foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks)
            {
                int chunkId = chunk.ID;

                if (chunk.Cases.Length == 1 && chunk.Cases[0] == null)
                {
                    defaultChunkId = chunkId;
                }
                else
                {
                    foreach (Expression expression in chunk.Cases)
                    {
                        if (isInt)
                        {
                            integersToChunkIds[((IntegerConstant)expression).Value] = chunkId;
                        }
                        else
                        {
                            stringsToChunkIds[((StringConstant)expression).Value] = chunkId;
                        }
                    }
                }

                chunkIdsToOffsets[chunkId] = chunkBuffer.Size;

                bcc.Compile(parser, chunkBuffer, chunk.Code);
            }

            chunkBuffer.ResolveBreaks();

            int defaultOffsetLength = defaultChunkId == -1
                ? chunkBuffer.Size
                : chunkIdsToOffsets[defaultChunkId];

            List <int> args = new List <int>()
            {
                defaultOffsetLength
            };

            if (isInt)
            {
                foreach (int caseValue in integersToChunkIds.Keys.OrderBy(_ => _))
                {
                    int chunkId = integersToChunkIds[caseValue];
                    int offset  = chunkIdsToOffsets[chunkId];
                    args.Add(caseValue);
                    args.Add(offset);
                }
            }
            else
            {
                foreach (string caseValue in stringsToChunkIds.Keys.OrderBy(_ => _))
                {
                    int chunkId = stringsToChunkIds[caseValue];
                    int offset  = chunkIdsToOffsets[chunkId];
                    args.Add(parser.GetStringConstant(caseValue));
                    args.Add(offset);
                }
            }

            buffer.Add(
                switchStatement.FirstToken,
                isInt ? OpCode.SWITCH_INT : OpCode.SWITCH_STRING,
                args.ToArray());

            buffer.Concat(chunkBuffer);
        }
Exemplo n.º 24
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Assignment assignment)
        {
            Expression target = assignment.Target;
            Expression value  = assignment.Value;

            ResolvedType targetAssignmentType = target.ResolvedType;

            if (targetAssignmentType == null)
            {
                throw new Exception();                               // should be ANY if no type is set.
            }
            if (value.ResolvedType == ResolvedType.ANY &&
                targetAssignmentType != ResolvedType.ANY)
            {
                value = new Cast(value.FirstToken, targetAssignmentType, value, value.Owner, false);
            }

            if (assignment.Op == Ops.EQUALS)
            {
                if (assignment.Target is Variable)
                {
                    Variable varTarget = (Variable)assignment.Target;
                    bcc.CompileExpression(parser, buffer, value, true);
                    VariableId varId = varTarget.VarId;
                    if (varId.UsedByClosure)
                    {
                        buffer.Add(assignment.OpToken, OpCode.ASSIGN_CLOSURE, varId.ClosureID);
                    }
                    else
                    {
                        buffer.Add(assignment.OpToken, OpCode.ASSIGN_LOCAL, varId.ID);
                    }
                }
                else if (assignment.Target is BracketIndex)
                {
                    BracketIndex bi = (BracketIndex)assignment.Target;
                    bcc.CompileExpression(parser, buffer, bi.Root, true);
                    bcc.CompileExpression(parser, buffer, bi.Index, true);
                    bcc.CompileExpression(parser, buffer, value, true);
                    buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0);
                }
                else if (assignment.Target is DotField)
                {
                    DotField dotStep = (DotField)assignment.Target;
                    if (dotStep.Root is ThisKeyword)
                    {
                        bcc.CompileExpression(parser, buffer, value, true);
                        buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, parser.GetId(dotStep.FieldToken.Value));
                    }
                    else
                    {
                        bcc.CompileExpression(parser, buffer, dotStep.Root, true);
                        bcc.CompileExpression(parser, buffer, value, true);
                        int nameId             = parser.GetId(dotStep.FieldToken.Value);
                        int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale);
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_FIELD,
                            nameId,
                            0,
                            localeScopedNameId,
                            assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID,
                            assignment.CompilationScope.ScopeNumId,
                            -1, 0);
                    }
                }
                else if (assignment.Target is FieldReference)
                {
                    bcc.CompileExpression(parser, buffer, value, true);
                    FieldReference fieldReference = (FieldReference)assignment.Target;
                    if (fieldReference.Field.Modifiers.HasStatic)
                    {
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_STATIC_FIELD,
                            ((ClassDefinition)fieldReference.Field.Owner).ClassID,
                            fieldReference.Field.StaticMemberID);
                    }
                    else
                    {
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_THIS_FIELD,
                            fieldReference.Field.MemberID);
                    }
                }
                else
                {
                    throw new Exception("This shouldn't happen.");
                }
            }
            else
            {
                Ops op = assignment.Op;
                if (assignment.Target is Variable)
                {
                    Variable   varTarget = (Variable)assignment.Target;
                    VariableId varId     = varTarget.VarId;
                    bool       isClosure = varId.UsedByClosure;
                    int        scopeId   = isClosure ? varId.ClosureID : varId.ID;

                    buffer.Add(varTarget.FirstToken, isClosure ? OpCode.DEREF_CLOSURE : OpCode.LOCAL, scopeId);
                    bcc.CompileExpression(parser, buffer, value, true);
                    buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op);
                    buffer.Add(assignment.Target.FirstToken, isClosure ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId);
                }
                else if (assignment.Target is DotField)
                {
                    DotField dotExpr            = (DotField)assignment.Target;
                    int      fieldId            = parser.GetId(dotExpr.FieldToken.Value);
                    int      localeScopedStepId = parser.GetLocaleCount() * fieldId + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale);
                    bcc.CompileExpression(parser, buffer, dotExpr.Root, true);
                    if (!(dotExpr.Root is ThisKeyword))
                    {
                        buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 1);
                    }
                    buffer.Add(
                        dotExpr.DotToken,
                        OpCode.DEREF_DOT,
                        fieldId,
                        localeScopedStepId,
                        assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID,
                        assignment.CompilationScope.ScopeNumId,
                        -1, 0);
                    bcc.CompileExpression(parser, buffer, value, true);
                    buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op);
                    if (dotExpr.Root is ThisKeyword)
                    {
                        buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldId);
                    }
                    else
                    {
                        int localeScopedNameId = fieldId * parser.GetLocaleCount() + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale);
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_FIELD,
                            fieldId,
                            0,
                            localeScopedNameId,
                            assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID,
                            assignment.CompilationScope.ScopeNumId,
                            -1, 0);
                    }
                }
                else if (assignment.Target is BracketIndex)
                {
                    BracketIndex indexExpr = (BracketIndex)assignment.Target;
                    bcc.CompileExpression(parser, buffer, indexExpr.Root, true);
                    bcc.CompileExpression(parser, buffer, indexExpr.Index, true);
                    buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 2);
                    buffer.Add(indexExpr.BracketToken, OpCode.INDEX);
                    bcc.CompileExpression(parser, buffer, value, true);
                    buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op);
                    buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0);
                }
                else if (assignment.Target is FieldReference)
                {
                    FieldReference fieldRef = (FieldReference)assignment.Target;
                    FieldReferenceEncoder.Compile(parser, buffer, fieldRef, true);
                    bcc.CompileExpression(parser, buffer, value, true);
                    buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op);

                    if (fieldRef.Field.Modifiers.HasStatic)
                    {
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_STATIC_FIELD,
                            ((ClassDefinition)fieldRef.Field.Owner).ClassID,
                            fieldRef.Field.StaticMemberID);
                    }
                    else
                    {
                        buffer.Add(
                            assignment.OpToken,
                            OpCode.ASSIGN_THIS_FIELD,
                            fieldRef.Field.MemberID);
                    }
                }
                else
                {
                    throw new ParserException(assignment.OpToken, "Assignment is not allowed on this sort of expression.");
                }
            }
        }
Exemplo n.º 25
0
        public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Increment increment, bool outputUsed)
        {
            if (!outputUsed)
            {
                throw new Exception("This should have been optimized into a += or -=");
            }

            if (increment.Root is Variable)
            {
                // OpCode re-use be damned. This should be not one, but two top-level op codes.
                // INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true)
                // In fact, the code here in its current form is actually WRONG because someString++ will have
                // a '1' appended to it when it really should be an error if the variable is not an integer.
                // Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed.
                Variable   variable     = (Variable)increment.Root;
                VariableId varId        = variable.VarId;
                bool       isClosureVar = varId.UsedByClosure;
                int        scopeId      = isClosureVar ? varId.ClosureID : varId.ID;
                bcc.CompileExpression(parser, buffer, increment.Root, true);
                if (increment.IsPrefix)
                {
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
                    buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId);
                }
                else
                {
                    buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId);
                }
            }
            else if (increment.Root is BracketIndex)
            {
                BracketIndex bracketIndex = (BracketIndex)increment.Root;
                bcc.CompileExpression(parser, buffer, bracketIndex.Root, true);
                bcc.CompileExpression(parser, buffer, bracketIndex.Index, true);
                buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2);
                buffer.Add(bracketIndex.BracketToken, OpCode.INDEX);
                if (increment.IsPrefix)
                {
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1);
                }
                else
                {
                    buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT);
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0);
                }
            }
            else if (increment.Root is DotField)
            {
                DotField dotStep = (DotField)increment.Root;
                bcc.CompileExpression(parser, buffer, dotStep.Root, true);
                buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
                int nameId             = parser.GetId(dotStep.FieldToken.Value);
                int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale);
                int originClassId      = increment.ClassOwner == null ? -1 : increment.ClassOwner.ClassID;
                int originAssemblyId   = increment.CompilationScope.ScopeNumId;
                buffer.Add(
                    dotStep.DotToken,
                    OpCode.DEREF_DOT,
                    nameId,
                    localeScopedNameId,
                    originClassId,
                    increment.CompilationScope.ScopeNumId,
                    -1, 0);
                if (increment.IsPrefix)
                {
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 1, localeScopedNameId, originClassId, originAssemblyId, -1, 0);
                }
                else
                {
                    buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2);
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, originClassId, originAssemblyId, -1, 0);
                    buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP);
                }
            }
            else if (increment.Root is FieldReference)
            {
                FieldReference  fr       = (FieldReference)increment.Root;
                bool            isStatic = fr.Field.Modifiers.HasStatic;
                ClassDefinition cd       = (ClassDefinition)fr.Field.Owner;
                int             memberId = isStatic ? fr.Field.StaticMemberID : fr.Field.MemberID;

                bcc.CompileExpression(parser, buffer, fr, true);
                if (increment.IsPrefix)
                {
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                    buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
                }
                else
                {
                    buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
                    buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
                    buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION);
                }
                Token token = increment.IsPrefix ? increment.FirstToken : fr.FirstToken;
                if (isStatic)
                {
                    buffer.Add(token, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fr.Field.Owner).ClassID, memberId);
                }
                else
                {
                    buffer.Add(token, OpCode.ASSIGN_THIS_FIELD, memberId);
                }
            }
            else
            {
                throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression.");
            }
        }