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);
        }
예제 #2
0
        private static void CompileInlinedLibraryFunctionCall(
            ByteCodeCompiler bcc,
            ParserContext parser,
            ByteBuffer buffer,
            FunctionCall userWrittenOuterFunctionCall,
            FunctionDefinition embedFunctionBeingInlined,
            bool outputUsed)
        {
            Expression coreOrLibFunctionBeingInlined = ((ReturnStatement)embedFunctionBeingInlined.Code[0]).Expression;

            int embedFuncLength       = embedFunctionBeingInlined.ArgNames.Length;
            int userProvidedArgLength = userWrittenOuterFunctionCall.Args.Length;

            if (userProvidedArgLength > embedFuncLength)
            {
                // TODO: can this be removed? Isn't this caught elsewhere?
                throw new ParserException(userWrittenOuterFunctionCall.ParenToken, "More arguments were passed to this function than allowed.");
            }

            // First go through the args provided and map them to the arg names of the embed function that's being inlined.
            Dictionary <string, Expression> userProvidedAndImplicitArgumentsByArgName = new Dictionary <string, Expression>();

            for (int i = 0; i < embedFuncLength; ++i)
            {
                Expression argValue;
                if (i < userProvidedArgLength)
                {
                    argValue = userWrittenOuterFunctionCall.Args[i];
                }
                else
                {
                    argValue = embedFunctionBeingInlined.DefaultValues[i];
                    if (argValue == null)
                    {
                        throw new ParserException(userWrittenOuterFunctionCall.ParenToken, "Not enough arguments were supplied to this function.");
                    }
                }
                userProvidedAndImplicitArgumentsByArgName[embedFunctionBeingInlined.ArgNames[i].Value] = argValue;
            }

            CniFunctionInvocation  cniFunctionCall  = coreOrLibFunctionBeingInlined as CniFunctionInvocation;
            CoreFunctionInvocation coreFunctionCall = coreOrLibFunctionBeingInlined as CoreFunctionInvocation;

            if (cniFunctionCall == null && coreFunctionCall == null)
            {
                throw new InvalidOperationException(); // This shouldn't happen. The body of the library function should have been verified by the resolver before getting to this state.
            }

            Expression[] innermostArgList = cniFunctionCall != null
                ? cniFunctionCall.Args
                : coreFunctionCall.Args;

            // This is the new list of arguments that will be passed to the inner underlying lib/core function.
            List <Expression> finalArguments = new List <Expression>();

            Expression arg;

            for (int i = 0; i < innermostArgList.Length; ++i)
            {
                arg = innermostArgList[i];
                if (arg is Variable)
                {
                    string argName = ((Variable)innermostArgList[i]).Name;
                    finalArguments.Add(userProvidedAndImplicitArgumentsByArgName[argName]);
                }
                else if (arg.IsLiteral || arg is FieldReference)
                {
                    finalArguments.Add(arg);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            if (cniFunctionCall != null)
            {
                CniFunctionInvocationEncoder.Compile(
                    bcc,
                    parser,
                    buffer,
                    cniFunctionCall,
                    finalArguments.ToArray(),
                    userWrittenOuterFunctionCall.ParenToken,
                    outputUsed);
            }
            else
            {
                CoreFunctionInvocationEncoder.Compile(
                    bcc,
                    parser,
                    buffer,
                    coreFunctionCall,
                    finalArguments.ToArray(),
                    userWrittenOuterFunctionCall.ParenToken,
                    outputUsed);
            }
        }
예제 #3
0
        public void TranslateCoreFunctionInvocation(TranspilerContext sb, CoreFunctionInvocation coreFuncInvocation)
        {
            Expression[] args = coreFuncInvocation.Args;
            switch (coreFuncInvocation.Function)
            {
            case CoreFunction.ARRAY_GET: this.TranslateArrayGet(sb, args[0], args[1]); break;

            case CoreFunction.ARRAY_JOIN: this.TranslateArrayJoin(sb, args[0], args[1]); break;

            case CoreFunction.ARRAY_LENGTH: this.TranslateArrayLength(sb, args[0]); break;

            case CoreFunction.ARRAY_SET: this.TranslateArraySet(sb, args[0], args[1], args[2]); break;

            case CoreFunction.BASE64_TO_STRING: this.TranslateBase64ToString(sb, args[0]); break;

            case CoreFunction.CHAR_TO_STRING: this.TranslateCharToString(sb, args[0]); break;

            case CoreFunction.CHR: this.TranslateChr(sb, args[0]); break;

            case CoreFunction.CURRENT_TIME_SECONDS: this.TranslateCurrentTimeSeconds(sb); break;

            case CoreFunction.DICTIONARY_CONTAINS_KEY: this.TranslateDictionaryContainsKey(sb, args[0], args[1]); break;

            case CoreFunction.DICTIONARY_GET: this.TranslateDictionaryGet(sb, args[0], args[1]); break;

            case CoreFunction.DICTIONARY_KEYS: this.TranslateDictionaryKeys(sb, args[0]); break;

            case CoreFunction.DICTIONARY_NEW: this.TranslateDictionaryNew(sb, coreFuncInvocation.ResolvedType.Generics[0], coreFuncInvocation.ResolvedType.Generics[1]); break;

            case CoreFunction.DICTIONARY_REMOVE: this.TranslateDictionaryRemove(sb, args[0], args[1]); break;

            case CoreFunction.DICTIONARY_SET: this.TranslateDictionarySet(sb, args[0], args[1], args[2]); break;

            case CoreFunction.DICTIONARY_SIZE: this.TranslateDictionarySize(sb, args[0]); break;

            case CoreFunction.DICTIONARY_VALUES: this.TranslateDictionaryValues(sb, args[0]); break;

            case CoreFunction.EMIT_COMMENT: this.TranslateEmitComment(sb, ((InlineConstant)args[0]).Value.ToString()); break;

            case CoreFunction.EXTENSIBLE_CALLBACK_INVOKE: this.TranslateExtensibleCallbackInvoke(sb, args[0], args[1]); break;

            case CoreFunction.FLOAT_BUFFER_16: this.TranslateFloatBuffer16(sb); break;

            case CoreFunction.FLOAT_DIVISION: this.TranslateFloatDivision(sb, args[0], args[1]); break;

            case CoreFunction.FLOAT_TO_STRING: this.TranslateFloatToString(sb, args[0]); break;

            case CoreFunction.GET_FUNCTION: this.TranslateGetFunction(sb, args[0]); break;

            case CoreFunction.INT: this.TranslateFloatToInt(sb, args[0]); break;

            case CoreFunction.INT_BUFFER_16: this.TranslateIntBuffer16(sb); break;

            case CoreFunction.INT_TO_STRING: this.TranslateIntToString(sb, args[0]); break;

            case CoreFunction.INTEGER_DIVISION: this.TranslateIntegerDivision(sb, args[0], args[1]); break;

            case CoreFunction.IS_VALID_INTEGER: this.TranslateIsValidInteger(sb, args[0]); break;

            case CoreFunction.LIST_ADD: this.TranslateListAdd(sb, args[0], args[1]); break;

            case CoreFunction.LIST_CLEAR: this.TranslateListClear(sb, args[0]); break;

            case CoreFunction.LIST_CONCAT: this.TranslateListConcat(sb, args[0], args[1]); break;

            case CoreFunction.LIST_GET: this.TranslateListGet(sb, args[0], args[1]); break;

            case CoreFunction.LIST_INSERT: this.TranslateListInsert(sb, args[0], args[1], args[2]); break;

            case CoreFunction.LIST_JOIN_CHARS: this.TranslateListJoinChars(sb, args[0]); break;

            case CoreFunction.LIST_JOIN_STRINGS: this.TranslateListJoinStrings(sb, args[0], args[1]); break;

            case CoreFunction.LIST_NEW: this.TranslateListNew(sb, coreFuncInvocation.ResolvedType.Generics[0]); break;

            case CoreFunction.LIST_POP: this.TranslateListPop(sb, args[0]); break;

            case CoreFunction.LIST_REMOVE_AT: this.TranslateListRemoveAt(sb, args[0], args[1]); break;

            case CoreFunction.LIST_REVERSE: this.TranslateListReverse(sb, args[0]); break;

            case CoreFunction.LIST_SET: this.TranslateListSet(sb, args[0], args[1], args[2]); break;

            case CoreFunction.LIST_SHUFFLE: this.TranslateListShuffle(sb, args[0]); break;

            case CoreFunction.LIST_SIZE: this.TranslateListSize(sb, args[0]); break;

            case CoreFunction.LIST_TO_ARRAY: this.TranslateListToArray(sb, args[0]); break;

            case CoreFunction.MATH_ARCCOS: this.TranslateMathArcCos(sb, args[0]); break;

            case CoreFunction.MATH_ARCSIN: this.TranslateMathArcSin(sb, args[0]); break;

            case CoreFunction.MATH_ARCTAN: this.TranslateMathArcTan(sb, args[0], args[1]); break;

            case CoreFunction.MATH_COS: this.TranslateMathCos(sb, args[0]); break;

            case CoreFunction.MATH_LOG: this.TranslateMathLog(sb, args[0]); break;

            case CoreFunction.MATH_POW: this.TranslateMathPow(sb, args[0], args[1]); break;

            case CoreFunction.MATH_SIN: this.TranslateMathSin(sb, args[0]); break;

            case CoreFunction.MATH_TAN: this.TranslateMathTan(sb, args[0]); break;

            case CoreFunction.MULTIPLY_LIST: this.TranslateMultiplyList(sb, args[0], args[1]); break;

            case CoreFunction.ORD: this.TranslateOrd(sb, args[0]); break;

            case CoreFunction.PARSE_FLOAT_UNSAFE: this.TranslateParseFloatUnsafe(sb, args[0]); break;

            case CoreFunction.PARSE_INT: this.TranslateParseInt(sb, args[0]); break;

            case CoreFunction.PRINT_STDERR: this.TranslatePrintStdErr(sb, args[0]); break;

            case CoreFunction.PRINT_STDOUT: this.TranslatePrintStdOut(sb, args[0]); break;

            case CoreFunction.RANDOM_FLOAT: this.TranslateRandomFloat(sb); break;

            case CoreFunction.SORTED_COPY_OF_INT_ARRAY: this.TranslateSortedCopyOfIntArray(sb, args[0]); break;

            case CoreFunction.SORTED_COPY_OF_STRING_ARRAY: this.TranslateSortedCopyOfStringArray(sb, args[0]); break;

            case CoreFunction.STRING_APPEND: this.TranslateStringAppend(sb, args[0], args[1]); break;

            case CoreFunction.STRING_BUFFER_16: this.TranslateStringBuffer16(sb); break;

            case CoreFunction.STRING_CHAR_AT: this.TranslateStringCharAt(sb, args[0], args[1]); break;

            case CoreFunction.STRING_CHAR_CODE_AT: this.TranslateStringCharCodeAt(sb, args[0], args[1]); break;

            case CoreFunction.STRING_COMPARE_IS_REVERSE: this.TranslateStringCompareIsReverse(sb, args[0], args[1]); break;

            case CoreFunction.STRING_CONCAT_ALL: if (args.Length == 2)
                {
                    this.TranslateStringConcatPair(sb, args[0], args[1]);
                }
                else
                {
                    this.TranslateStringConcatAll(sb, args);
                } break;

            case CoreFunction.STRING_CONTAINS: this.TranslateStringContains(sb, args[0], args[1]); break;

            case CoreFunction.STRING_ENDS_WITH: this.TranslateStringEndsWith(sb, args[0], args[1]); break;

            case CoreFunction.STRING_EQUALS: this.TranslateStringEquals(sb, args[0], args[1]); break;

            case CoreFunction.STRING_FROM_CHAR_CODE: this.TranslateStringFromCharCode(sb, args[0]); break;

            case CoreFunction.STRING_INDEX_OF: if (args.Length == 2)
                {
                    this.TranslateStringIndexOf(sb, args[0], args[1]);
                }
                else
                {
                    this.TranslateStringIndexOfWithStart(sb, args[0], args[1], args[2]);
                } break;

            case CoreFunction.STRING_LENGTH: this.TranslateStringLength(sb, args[0]); break;

            case CoreFunction.STRING_REPLACE: this.TranslateStringReplace(sb, args[0], args[1], args[2]); break;

            case CoreFunction.STRING_REVERSE: this.TranslateStringReverse(sb, args[0]); break;

            case CoreFunction.STRING_SPLIT: this.TranslateStringSplit(sb, args[0], args[1]); break;

            case CoreFunction.STRING_STARTS_WITH: this.TranslateStringStartsWith(sb, args[0], args[1]); break;

            case CoreFunction.STRING_SUBSTRING: this.TranslateStringSubstring(sb, args[0], args[1], args[2]); break;

            case CoreFunction.STRING_SUBSTRING_IS_EQUAL_TO: this.TranslateStringSubstringIsEqualTo(sb, args[0], args[1], args[2]); break;

            case CoreFunction.STRING_TO_LOWER: this.TranslateStringToLower(sb, args[0]); break;

            case CoreFunction.STRING_TO_UPPER: this.TranslateStringToUpper(sb, args[0]); break;

            case CoreFunction.STRING_TRIM: this.TranslateStringTrim(sb, args[0]); break;

            case CoreFunction.STRING_TRIM_END: this.TranslateStringTrimEnd(sb, args[0]); break;

            case CoreFunction.STRING_TRIM_START: this.TranslateStringTrimStart(sb, args[0]); break;

            case CoreFunction.STRINGBUILDER_ADD: this.TranslateStringBuilderAdd(sb, args[0], args[1]); break;

            case CoreFunction.STRINGBUILDER_CLEAR: this.TranslateStringBuilderClear(sb, args[0]); break;

            case CoreFunction.STRINGBUILDER_TOSTRING: this.TranslateStringBuilderToString(sb, args[0]); break;

            case CoreFunction.STRONG_REFERENCE_EQUALITY: this.TranslateStrongReferenceEquality(sb, args[0], args[1]); break;

            case CoreFunction.TO_CODE_STRING: this.TranslateToCodeString(sb, args[0]); break;

            case CoreFunction.TRY_PARSE_FLOAT: this.TranslateTryParseFloat(sb, args[0], args[1]); break;

            case CoreFunction.DICTIONARY_TRY_GET:
                throw new ParserException(coreFuncInvocation.FirstToken, "Dictionary's TryGet method cannot be called like this. It must be assigned to a variable directly. This is due to a restriction in how this can get transpiled to certain languages.");

            default: throw new NotImplementedException(coreFuncInvocation.Function.ToString());
            }
        }