static string BuildArgumentValues( IFunctionInstance function, NamedCollection <IArgumentDeclaration> arguments, INamedExpressionTuple expressions, ICppScope scope, string kind) { if (arguments.IsEmpty()) { return(string.Empty); } var name = scope.MakeLocalName(); var typeName = GetFunctionTypeName(function.Name, kind); scope.Runtime.AddLine($"{typeName} {name};"); var argN = 0; foreach (var expression in expressions.Tuple) { var argument = arguments[argN]; argN++; var value = Dynamic((dynamic)expression.Expression, scope); if (argument.IsAssignable) { scope.Runtime.AddLine($"{name}.{CppEscape(argument.Name)} = &{value};"); } else { scope.Runtime.AddLine($"{name}.{CppEscape(argument.Name)} = {value};"); } } return(name); }
static void BuildArgumentValues( ILocalValueScope localValues, INamedExpressionTuple expressions, ILocalIdentifierScope argumentScope, ArgumentInstanceCollection arguments, IContext argumentContext, IContext functionContext) { var argN = 0; foreach (var expression in expressions.Tuple) { var argumentName = expression.Name; if (string.IsNullOrEmpty(argumentName)) { argumentName = arguments[argN].Name; argN++; } var argument = (IArgumentInstance)argumentScope[argumentName]; var value = Dynamic((dynamic)expression.Expression, argumentContext); var casted = ImplicitCast(value, argument.Type); localValues.Add(argument, casted); } for (; argN < arguments.Count; argN++) { var argument = arguments[argN]; var value = Dynamic((dynamic)argument.Argument.Value, functionContext); localValues.Add(argument, value); } }
void AssertNamedExpressionTuple(INamedExpressionTuple expected, INamedExpressionTuple actual, string label = "") { Assert.AreEqual(expected.Tuple.Count, actual.Tuple.Count, $"{label}.Tuple.Count"); for (var i = 0; i < expected.Tuple.Count; i++) { AssertNamedExpression(expected.Tuple[i], actual.Tuple[i], label: $"{label}.Tuple[{i}]"); } }
static ITypedValue ImplicitCast(INamedExpressionTuple tuple, IModuleInstance type) { if (tuple.Tuple.Count == 1) { return(ImplicitCast((dynamic)tuple.Tuple.First().Expression, type)); } throw new ArgumentException(message: "Invalid argument tuple"); }
static IExpression Dynamic(INamedExpressionTuple expressionTuple, IContext context) { IExpression result = null; foreach (var sub in expressionTuple.Tuple) { result = Dynamic((dynamic)sub.Expression, context); } return(result); }
static string Dynamic(INamedExpressionTuple expressionTuple, ICppScope scope) { string result = null; foreach (var sub in expressionTuple.Tuple) { result = Dynamic((dynamic)sub.Expression, scope); } return(result); }
static IExpression ParseResolved( IFunctionOverloads function, INamedExpressionTuple leftArguments, IEnumerator <TokenData> tokens, IContext context, ref bool done) { var pool = function.Overloads; return(ParseFunctionOverloads(pool, leftArguments, tokens, context, ref done)); }
static IExpression CreateFunctionInvocation( IList <IFunctionInstance> pool, TextFileRange range, INamedExpressionTuple leftArguments, INamedExpressionTuple rightArguments) { var filteredPool = FilterFunctionLeftArguments(pool, leftArguments); filteredPool = FilterFunctionRightArguments(filteredPool, rightArguments); return(filteredPool.Count != 1 ? null : CreateFunctionInvocation(filteredPool.First(), range, leftArguments, rightArguments)); // TODO: proper error handling }
static IList <IFunctionInstance> ParseAndFilterFunctionRightArguments( IList <IFunctionInstance> pool, ref INamedExpressionTuple rightArguments, IEnumerator <TokenData> tokens, IContext context, ref bool done) { if (!pool.IsEmpty() && (pool.Count != 1 || pool[0].RightArguments.Count != 0)) { rightArguments = Parse(tokens, context, ref done); return(FilterFunctionRightArguments(pool, rightArguments)); } return(pool); }
static IExpression CreateFunctionInvocation( IFunctionInstance function, TextFileRange range, INamedExpressionTuple leftArguments, INamedExpressionTuple rightArguments) { var invocation = new FunctionInvocation { Function = function, Range = range, Left = AssignArguments(function.LeftArguments, leftArguments), Right = AssignArguments(function.RightArguments, rightArguments) }; return(invocation); }
static IExpression ParseResolved( ITypedInstance typed, INamedExpressionTuple leftArguments, IEnumerator <TokenData> tokens, IContext context, ref bool done) { var result = new TypedReference { Range = tokens.Current.Range, Type = typed.Type, Instance = typed }; if (!tokens.MoveNext()) { done = true; } return(result); }
static IExpression ParseFunctionOverloads(IList <IFunctionInstance> pool, INamedExpressionTuple leftArguments, IEnumerator <TokenData> tokens, IContext context, ref bool done) { var range = tokens.Current.Range; INamedExpressionTuple rightArguments = new NamedExpressionTuple(); if (!tokens.MoveNext()) { done = true; return(CreateFunctionInvocation(pool, range, leftArguments, rightArguments)); } var filteredPool = FilterFunctionLeftArguments(pool, leftArguments); filteredPool = ParseAndFilterFunctionRightArguments(filteredPool, ref rightArguments, tokens, context, ref done); if (filteredPool.Count != 1) { return(null); } // TODO: proper error handling return(CreateFunctionInvocation(filteredPool.First(), range, leftArguments, rightArguments)); }
static void ExtractArgumentReferenceValues( ILocalValueScope localValues, INamedExpressionTuple expressions, ArgumentInstanceCollection arguments, IContext callerContext) { var argN = 0; foreach (var expression in expressions.Tuple) { var argument = arguments[argN]; argN++; if (argument.Argument.IsAssignable && expression.Expression is ITypedReference reference) { var referenceDecl = callerContext.Values[reference.Instance]; var value = localValues[argument]; var casted = ImplicitCast(value, referenceDecl.Type); Array.Copy(casted.Data, referenceDecl.Data, referenceDecl.Data.Length); } } }
static INamedExpressionTuple ParseResult(INamedExpressionTuple result, IEnumerator <TokenData> tokens, IContext context, ref bool done) { while (!done) { var token = tokens.Current; switch (token.Type) { case Token.OperatorLiteral: var operatorLiteral = (IIdentifierLiteral)token.Data; var itentifyerLiteralList = new List <TokenData>(); string operatorLiteralContent = operatorLiteral.Content; string operatorLiteralContentTail = ""; string notFoundLiteral = ""; while (!operatorLiteralContent.IsEmpty()) { if (operatorLiteralContent == "&") { if (!tokens.MoveNext()) { done = true; } if (done) { return(result); // TODO: report error: missing tokens } var inner = Parse(tokens, context, ref done); var execResult = CompileTime.Execute(inner, context); if (execResult != null) { if (execResult is INamedExpressionTuple execNamedTuple) { result.Tuple.AddRange(execNamedTuple.Tuple); } else { result.Tuple.Add(new NamedExpression { Expression = execResult }); } } continue; } var resolve = context.Identifiers[operatorLiteralContent]; if (resolve == null) { if (operatorLiteralContent.Length == 1) { notFoundLiteral += operatorLiteralContent; operatorLiteralContent = operatorLiteralContentTail; operatorLiteralContentTail = ""; } else { operatorLiteralContentTail = operatorLiteralContent.Last() + operatorLiteralContentTail; operatorLiteralContent = operatorLiteralContent.Substring(0, operatorLiteralContent.Length - 1); } } else { if (!notFoundLiteral.IsEmpty()) { itentifyerLiteralList.Add(new TokenData { Type = Token.IdentifierLiteral, Data = new IdentifierLiteral { Content = notFoundLiteral } }); notFoundLiteral = ""; } itentifyerLiteralList.Add(new TokenData { Type = Token.IdentifierLiteral, Data = new IdentifierLiteral { Content = operatorLiteralContent } // TODO Error and Range }); operatorLiteralContent = operatorLiteralContentTail; operatorLiteralContentTail = ""; } } if (!notFoundLiteral.IsEmpty()) { itentifyerLiteralList.Add(new TokenData { Type = Token.IdentifierLiteral, Data = new IdentifierLiteral { Content = notFoundLiteral } }); } using (var newTokens = itentifyerLiteralList.Before(tokens).GetEnumerator()) { return(ParseResult(result, newTokens, context, ref done)); } case Token.IdentifierLiteral: var identifierLiteral = (IIdentifierLiteral)token.Data; var resolved = context.Identifiers[identifierLiteral.Content]; if (null != resolved) { var subexpression = ParseResolved((dynamic)resolved, result, tokens, context, ref done); result.Tuple.Add(new NamedExpression { Expression = subexpression ?? identifierLiteral }); continue; } result.Tuple.Add(new NamedExpression { Expression = identifierLiteral }); break; case Token.StringLiteral: var stringLiteral = (IStringLiteral)token.Data; result.Tuple.Add(new NamedExpression { Expression = stringLiteral }); break; case Token.NumberLiteral: var numberLiteral = (INumberLiteral)token.Data; result.Tuple.Add(new NamedExpression { Expression = numberLiteral }); break; case Token.BlockStartIndentation: var tokenBlock = (IBlockLiteral)token.Data; result.Tuple.Add(new NamedExpression { Expression = tokenBlock }); break; } if (done) { break; } if (!tokens.MoveNext()) { done = true; } } return(result); }
static INamedExpressionTuple AssignArguments(NamedCollection <IArgumentInstance> instances, INamedExpressionTuple arguments) { var result = new NamedExpressionTuple(); var o = arguments.Tuple.Count - instances.Count; foreach (var instance in instances) { // TODO: check that conversion exists result.Tuple.Add(arguments.Tuple[o]); arguments.Tuple.RemoveAt(o); } // TODO: check that enough arguments are given return(result); }
static IList <IFunctionInstance> FilterFunctionRightArguments(IList <IFunctionInstance> pool, INamedExpressionTuple rightArguments) { return(pool.Where( f => f.Declaration.RightArguments == null || f.Declaration.MandatoryRightArgumentCount() <= rightArguments.Tuple.Count && (f.Declaration.MaxRightArgumentCount() == null || !(f.Declaration.MaxRightArgumentCount() < rightArguments.Tuple.Count))).ToList()); }
static IList <IFunctionInstance> FilterFunctionLeftArguments(IList <IFunctionInstance> pool, INamedExpressionTuple leftArguments) { return(pool.Where( f => { if (f.Declaration.LeftArguments == null) { return true; } if (f.Declaration.LeftArguments.Count > leftArguments.Tuple.Count) { return false; } var o = leftArguments.Tuple.Count - f.Declaration.LeftArguments.Count; foreach (var fArg in f.Declaration.LeftArguments) { var givenArg = leftArguments.Tuple[o]; if (!CanImplicitConvertExpressionTo(givenArg.Expression, fArg.Type)) { return false; } o++; } return f.Declaration.LeftArguments.Count <= leftArguments.Tuple.Count; }).ToList()); }