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); }
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); } }
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()); } }