static void Dynamic(IExpressionBlock block, ICppScope scope) { foreach (var blockExpression in block.Expressions) { Dynamic((dynamic)blockExpression, scope); } }
static void DeclareFunction(IFunctionDeclaration function, ICppScope scope) { DeclareArguments(function, function.LeftArguments, scope, kind: "Left"); DeclareArguments(function, function.RightArguments, scope, kind: "Right"); DeclareArguments(function, function.Results, scope, kind: "Result"); DeclareFunctionBody(function, scope); }
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 Dynamic(IIntrinsicExpression intrinsicExpression, ICppScope scope) { if (intrinsicExpression.Intrinsic is IFunctionIntrinsic func) { func.GenerateCpp(new CppIntrinsic { Scope = scope }); } }
static void MakeResultLocals(IEnumerable <IArgumentDeclaration> results, ICppScope scope) { foreach (var result in results) { var resultType = GetArgumentTypeName(result.Type); var resultName = CppEscape(result.Name); scope.Runtime.AddLine($"{resultType} {resultName};"); // TODO: initialize to default value } }
static string CreateGlobalDeclaration(ICppScope localScope, Action <ICppScope> action) { var scope = new CppScope { Globals = localScope.Globals }; action(scope); return(scope.Declaration.Build()); }
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 string BuildResultValues(IFunctionInstance function, ICppScope scope, ref string name) { var argumentDeclarations = function.Declaration.Results; if (argumentDeclarations.IsEmpty()) { return(string.Empty); } name = scope.MakeLocalName(); var typeName = GetFunctionTypeName(function.Name, kind: "Result"); return($"{typeName} {name} = "); }
static string Dynamic(IFunctionInvocation functionInvocation, ICppScope scope) { var function = functionInvocation.Function; if (function.Declaration.Implementation.Expressions.Count == 1 && function.Declaration.Implementation.Expressions.First() is IIntrinsicExpression) { scope.EnsureGlobal(function.Name, () => { return(CreateGlobalDeclaration(scope, subScope => DeclareFunction(function.Declaration, subScope))); }); } var leftArgs = BuildArgumentValues(function, function.Declaration.LeftArguments, functionInvocation.Left, scope, kind: "Left"); var rightArgs = BuildArgumentValues(function, function.Declaration.RightArguments, functionInvocation.Right, scope, kind: "Right"); var resultName = string.Empty; var resultArgs = BuildResultValues(function, scope, ref resultName); scope.Runtime.AddLine(BuildInvocation(function.Name, leftArgs, rightArgs, resultArgs)); return(resultName); }
static void DeclareFunctionBody(IFunctionDeclaration function, ICppScope scope) { var noResult = function.Results.IsEmpty(); var noLeft = function.LeftArguments.IsEmpty(); var noRight = function.RightArguments.IsEmpty(); var resultType = noResult ? "void" : GetFunctionTypeName(function.Name, kind: "Result"); var left = string.Empty; var leftLocal = string.Empty; var right = string.Empty; var rightLocal = string.Empty; if (!noLeft) { leftLocal = scope.MakeLocalName(hint: "left"); left = GetFunctionTypeName(function.Name, kind: "Left") + " " + leftLocal; } if (!noRight) { rightLocal = scope.MakeLocalName(hint: "right"); right = (noLeft ? "" : ", ") + GetFunctionTypeName(function.Name, kind: "Right") + " " + rightLocal; } scope.Declaration.AddLine($"inline {resultType} {CppEscape(function.Name)}({left}{right}) {{"); scope.WithDeclarationIndented( innerScope => { MakeArgumentLocals(function.LeftArguments, leftLocal, innerScope); MakeArgumentLocals(function.RightArguments, rightLocal, innerScope); MakeResultLocals(function.Results, innerScope); Dynamic(function.Implementation, innerScope); if (!noResult) { var resultLocal = scope.MakeLocalName(hint: "result"); innerScope.Runtime.AddLine($"{resultType} {resultLocal};"); AssignResultsFromLocals(resultLocal, function.Results, innerScope); innerScope.Runtime.AddLine($"return {resultLocal};"); } }); scope.Declaration.AddLine(line: "}"); }
static void Dynamic(IFunctionDeclaration functionDeclaration, ICppScope scope) { DeclareFunction(functionDeclaration, scope); }
// ReSharper disable once UnusedParameter.Local static string Dynamic(ITypedReference typedReference, ICppScope scope) { return(typedReference.Instance.Name); }
// ReSharper disable once UnusedParameter.Local static string Dynamic(INumberLiteral numberLiteral, ICppScope scope) { return(numberLiteral.IntegerPart); }
static void DeclareArguments(IFunctionDeclaration function, NamedCollection <IArgumentDeclaration> arguments, ICppScope scope, string kind) { if (arguments.IsEmpty()) { return; } var typeName = GetFunctionTypeName(function.Name, kind); scope.Declaration.AddLine($"struct {typeName} {{"); scope.WithDeclarationIndented( innerScope => { foreach (var argument in arguments) { var argTypeName = GetArgumentTypeName(argument.Type); var argName = CppEscape(argument.Name); if (argument.IsAssignable && kind != "Result") { innerScope.Declaration.AddLine($"{argTypeName}* {argName};"); if (arguments.Count == 1) { innerScope.Declaration.AddLine($"operator {argTypeName}() const {{ return *{argName}; }}"); } } else { innerScope.Declaration.AddLine($"{argTypeName} {argName};"); if (arguments.Count == 1) { innerScope.Declaration.AddLine($"operator {argTypeName}() const {{ return {argName}; }}"); } } } }); scope.Declaration.AddLine(line: "};"); }
static void MakeArgumentLocals(IEnumerable <IArgumentDeclaration> arguments, string arg, ICppScope scope) { foreach (var argument in arguments) { var argumentType = GetArgumentTypeName(argument.Type); var argName = CppEscape(argument.Name); if (argument.IsAssignable) { scope.Runtime.AddLine($"{argumentType} &{argName} = *std::move({arg}.{argName});"); } else { scope.Runtime.AddLine($"{argumentType} {argName} = std::move({arg}.{argName});"); } } }
static void AssignResultsFromLocals(string resultLocal, IEnumerable <IArgumentDeclaration> results, ICppScope scope) { foreach (var result in results) { var resultName = CppEscape(result.Name); scope.Runtime.AddLine($"{resultLocal}.{resultName} = std::move({resultName});"); } }