public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (scope.IsAssignment && TokenUtils.AllowedPrimitiveFunction(this.token.Type)) { /* * input: x -> right side, value * Perform the function like this: * * i := f{iota rho x} * (,x)[i] := value * * where 'f' is the monadic function */ DLR.Expression target = Node.TestMonadicToken(this.expression, Tokens.RAVEL) ? ((MonadicFunction)this.expression).Expression.Generate(scope) : this.expression.Generate(scope) ; // i:=(iota rho x) DLR.Expression indices = AST.Assign.BuildIndicesList(scope, target); // (,x)[f{i}] result = AST.Assign.BuildIndexing(scope, target, GenerateMonadic(scope, indices)); } else { result = GenerateMonadic(scope, this.expression.Generate(scope)); } return result; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); // arguments for the dynamic method call LinkedList<DLR.Expression> callArguments = new LinkedList<DLR.Expression>(); // add the parameters in !reverse! order if (this.leftarg != null) { callArguments.AddFirst(this.leftarg.Generate(scope)); } callArguments.AddFirst(this.function.Generate(scope)); if (this.condition != null) { callArguments.AddFirst(this.condition.Generate(scope)); } callArguments.AddFirst(this.rightarg.Generate(scope)); // add A+ environment as first argument for user defined functions callArguments.AddFirst(scope.GetRuntimeExpression()); callArguments.AddFirst(this.name.Generate(scope)); return AST.UserDefInvoke.BuildInvoke(runtime, callArguments); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (this.op.Function is Token || this.op.Function is Identifier || this.op.Function is Operator || this.op.Function is BuiltInOperator) { string methodName = String.Format("__built-in({0})__", this.op.ToString()); DLR.ParameterExpression functionVariable = DLR.Expression.Variable(typeof(AType), "__function__"); DLR.ParameterExpression methodEnvArg = DLR.Expression.Parameter(typeof(Aplus), "_ENV_ARG_"); DLR.ParameterExpression methodLeftArg = DLR.Expression.Parameter(typeof(AType), "_LEFT_ARG_"); DLR.ParameterExpression methodRightArg = DLR.Expression.Parameter(typeof(AType), "_RIGHT_ARG_"); DLR.LabelTarget methodReturnTarget = DLR.Expression.Label(typeof(AType), "_RESULT_"); DLR.Expression opFunction = GenerateOpFunction(scope, op); DLR.Expression codeBlock = DLR.Expression.Block( new DLR.ParameterExpression[] { functionVariable }, DLR.Expression.Assign(functionVariable, opFunction), DLR.Expression.IfThenElse( DLR.Expression.Equal(methodLeftArg, DLR.Expression.Constant(null)), BuildMonadicCase(scope, this.op, functionVariable, methodReturnTarget, methodEnvArg, methodRightArg ), BuildDyadicCase(scope, this.op, functionVariable, methodReturnTarget, methodEnvArg, methodRightArg, methodLeftArg ) ), DLR.Expression.Label(methodReturnTarget, DLR.Expression.Constant(default(AType), typeof(AType))) ); DLR.Expression lambda = DLR.Expression.Lambda<Func<Aplus, AType, AType, AType>>( codeBlock, methodName, new DLR.ParameterExpression[] { methodEnvArg, methodRightArg, methodLeftArg } ); result = DLR.Expression.Call( typeof(AFunc).GetMethod("CreateBuiltIn"), DLR.Expression.Constant(this.op.ToString()), lambda, DLR.Expression.Constant(lambda.ToString()), DLR.Expression.Constant(true) ); } else { // This will allow: (3;4) each // which will return the (3;4) result = this.op.Function.Generate(scope); } return result; }
/// <summary> /// Adds the passed parameter's name to the scope, and the parameterexpression to the expression linkedlist. /// </summary> /// <param name="methodScope">The scope.</param> /// <param name="methodParameters">The LinkedList to add.</param> /// <param name="parameter">The parameter to add.</param> private static void BuildParameterExpression( AplusScope methodScope, LinkedList <DLR.ParameterExpression> methodParameters, Identifier parameter) { if (parameter != null) { string name = parameter.Name; DLR.ParameterExpression expression = DLR.Expression.Parameter(typeof(AType), name); methodScope.Variables[name] = expression; methodParameters.AddFirst(expression); } }
private static DLR.Expression GenerateOpFunction(AplusScope scope, Operator op) { DLR.Expression function; if (op.isBuiltin) { function = AST.Node.BuiltInFunction((Token)op.Function).Generate(scope); } else { function = op.Function.Generate(scope); } return(function); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (this.nodeList.Count > 0) { result = DLR.Expression.Block(this.nodeList.Select(node => node.Generate(scope))); } else { result = DLR.Expression.Constant(Utils.ANull()); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { // generate the following code: // ($expression ? ($truecase) : ($falsecase)) DLR.Expression result = DLR.Expression.Condition( DLR.Expression.IsTrue( this.expression.Generate(scope), typeof(Helpers).GetMethod("BooleanTest") ), this.trueCase.Generate(scope), this.falseCase.Generate(scope) ); return(result); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (this.indexExpression != null) { // Generate each indexer expression in reverse order // the reverse order is to mimic the A+ evaulation order IEnumerable<DLR.Expression> indexerValues = this.indexExpression.Items.Reverse().Select( item => { return item.Generate(scope); } ); DLR.ParameterExpression indexerParam = DLR.Expression.Parameter(typeof(List<AType>), "__INDEX__"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { indexerParam }, DLR.Expression.Assign( indexerParam, DLR.Expression.Call( typeof(Helpers).GetMethod("BuildIndexerArray"), DLR.Expression.NewArrayInit(typeof(AType), indexerValues) ) ), DLR.Expression.Dynamic( scope.GetRuntime().GetIndexBinder(new DYN.CallInfo(indexerValues.Count())), typeof(object), this.item.Generate(scope), indexerParam ) ); } else { // in case of: a[]; result = DLR.Expression.Dynamic( scope.GetRuntime().GetIndexBinder(new DYN.CallInfo(0)), typeof(object), this.item.Generate(scope), DLR.Expression.Constant(null) ); } return result.To<AType>(); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (this.indexExpression != null) { // Generate each indexer expression in reverse order // the reverse order is to mimic the A+ evaulation order IEnumerable <DLR.Expression> indexerValues = this.indexExpression.Items.Reverse().Select( item => { return(item.Generate(scope)); } ); DLR.ParameterExpression indexerParam = DLR.Expression.Parameter(typeof(List <AType>), "__INDEX__"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { indexerParam }, DLR.Expression.Assign( indexerParam, DLR.Expression.Call( typeof(Helpers).GetMethod("BuildIndexerArray"), DLR.Expression.NewArrayInit(typeof(AType), indexerValues) ) ), DLR.Expression.Dynamic( scope.GetRuntime().GetIndexBinder(new DYN.CallInfo(indexerValues.Count())), typeof(object), this.item.Generate(scope), indexerParam ) ); } else { // in case of: a[]; result = DLR.Expression.Dynamic( scope.GetRuntime().GetIndexBinder(new DYN.CallInfo(0)), typeof(object), this.item.Generate(scope), DLR.Expression.Constant(null) ); } return(result.To <AType>()); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression func; if (this.function is Token) { Node wrappedFunction = new BuiltInFunction((Token)this.function); func = wrappedFunction.Generate(scope); } else { func = this.function.Generate(scope); } DLR.Expression result; if (isDyadic) { result = DLR.Expression.Call( DLR.Expression.Constant(DyadicOperatorInstance.Rank), DyadicOperatorInstance.Rank.GetType().GetMethod("Execute"), func, this.condition.Generate(scope), this.rightarg.Generate(scope), this.leftarg.Generate(scope), scope.GetRuntimeExpression() ); } else { result = DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Rank), MonadicOperatorInstance.Rank.GetType().GetMethod("Execute"), func, this.condition.Generate(scope), this.rightarg.Generate(scope), scope.GetRuntimeExpression() ); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression func; if (this.function is Token) { Node wrappedFunction = new BuiltInFunction((Token)this.function); func = wrappedFunction.Generate(scope); } else { func = this.function.Generate(scope); } DLR.Expression result; if (isDyadic) { result = DLR.Expression.Call( DLR.Expression.Constant(DyadicOperatorInstance.Rank), DyadicOperatorInstance.Rank.GetType().GetMethod("Execute"), func, this.condition.Generate(scope), this.rightarg.Generate(scope), this.leftarg.Generate(scope), scope.GetRuntimeExpression() ); } else { result = DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Rank), MonadicOperatorInstance.Rank.GetType().GetMethod("Execute"), func, this.condition.Generate(scope), this.rightarg.Generate(scope), scope.GetRuntimeExpression() ); } return result; }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; // Target condition DLR.Expression target = this.expression.Generate(scope); DLR.Expression defaultNode = this.defaultCase.Generate(scope); if (this.caseList.Length > 0) { List <DLR.SwitchCase> cases = new List <DLR.SwitchCase>(); for (int i = 0; i < this.caseList.Length; i += 2) { // Add each case // 1. (i+1) is the case's codeblock // 2. (i) is the case's test value cases.Add( DLR.Expression.SwitchCase( this.caseList[i + 1].Generate(scope), this.caseList[i].Generate(scope) ) ); } result = DLR.Expression.Switch( typeof(AType), target, defaultNode, comparisonMethod, cases ); } else { result = DLR.Expression.Block(target, defaultNode); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { string methodName = String.Format("__built-in({0})__", this.function.Text); DLR.ParameterExpression methodEnvArg = DLR.Expression.Parameter(typeof(Aplus), "_ENV_ARG_"); DLR.ParameterExpression methodLeftArg = DLR.Expression.Parameter(typeof(AType), "_LEFT_ARG_"); DLR.ParameterExpression methodRightArg = DLR.Expression.Parameter(typeof(AType), "_RIGHT_ARG_"); DLR.LabelTarget methodReturnTarget = DLR.Expression.Label(typeof(AType), "_RESULT_"); DLR.Expression codeBlock = DLR.Expression.Block( DLR.Expression.IfThenElse( DLR.Expression.Equal(methodLeftArg, DLR.Expression.Constant(null)), BuildMonadicCase(this.function, methodReturnTarget, methodEnvArg, methodRightArg), BuildDyadicCase(this.function, methodReturnTarget, methodEnvArg, methodRightArg, methodLeftArg) ), DLR.Expression.Label(methodReturnTarget, DLR.Expression.Constant(default(AType), typeof(AType))) ); DLR.Expression lambda = DLR.Expression.Lambda <Func <Aplus, AType, AType, AType> >( codeBlock, methodName, new DLR.ParameterExpression[] { methodEnvArg, methodRightArg, methodLeftArg } ); DLR.Expression result = DLR.Expression.Call( typeof(AFunc).GetMethod("CreateBuiltIn"), DLR.Expression.Constant(this.function.Text), lambda, DLR.Expression.Constant(this.function.Text), DLR.Expression.Constant(false) ); return(result); }
public override DLR.Expression Generate(AplusScope scope) { LinkedList <DLR.Expression> strandArguments = new LinkedList <DLR.Expression>(); // Add the paramters for the strand in a reverse order // thus enforcing the right-to-left execution order foreach (Node item in arguments) { strandArguments.AddFirst(item.Generate(scope)); } // Call the Runtime.Helpers.BuildStrand method // with the reversed paramaters wrappend in an AType[] array DLR.Expression result = DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), strandArguments ) ); return(result); }
public override DLR.Expression Generate(AplusScope scope) { LinkedList<DLR.Expression> strandArguments = new LinkedList<DLR.Expression>(); // Add the paramters for the strand in a reverse order // thus enforcing the right-to-left execution order foreach (Node item in arguments) { strandArguments.AddFirst(item.Generate(scope)); } // Call the Runtime.Helpers.BuildStrand method // with the reversed paramaters wrappend in an AType[] array DLR.Expression result = DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), strandArguments ) ); return result; }
public override DLR.Expression Generate(AplusScope scope) { AType result; // NOTE: do we need to generate this? most Constants will be encapsulated in ConstantList switch (this.type) { case ConstantType.CharacterConstant: result = Runtime.Helpers.BuildString(this.AsString); break; case ConstantType.Null: result = Utils.ANull(); break; case ConstantType.Integer: result = this.AsNumericAType; break; case ConstantType.NegativeInfinity: case ConstantType.PositiveInfinity: case ConstantType.Double: result = AFloat.Create(this.AsFloat); break; case ConstantType.Symbol: result = ASymbol.Create(this.AsString); break; case ConstantType.Undefined: default: // This Should NEVER happen throw new Exception("Should Not reach this point!.."); } return(DLR.Expression.Constant(result, typeof(AType))); }
public override DLR.Expression Generate(AplusScope scope) { // This parameter will store the return value DLR.ParameterExpression returnValue = DLR.ParameterExpression.Parameter(typeof(AType), "RETURN_VALUE"); DLR.LabelTarget breakLabel = DLR.Expression.Label(typeof(AType), "BREAK"); DLR.Expression result = DLR.Expression.Block( new DLR.ParameterExpression[] { returnValue }, // Assign the default return value: ANull DLR.Expression.Assign(returnValue, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Loop( DLR.Expression.Block( DLR.Expression.IfThen( // Test if the condition is equal to 0 // Invert the inner test's result DLR.Expression.Not( // This part will test if the condition is true (this means it is not 0) DLR.Expression.IsTrue( this.expression.Generate(scope), typeof(Helpers).GetMethod("BooleanTest") ) ), // Break out from the loop with the last computed value DLR.Expression.Break(breakLabel, returnValue) ), // Compute & assign the value DLR.Expression.Assign(returnValue, this.codeBlock.Generate(scope)) ), // The label where to jump in case of break breakLabel ) ); return result; }
public override DLR.Expression Generate(AplusScope scope) { // This parameter will store the return value DLR.ParameterExpression returnValue = DLR.ParameterExpression.Parameter(typeof(AType), "RETURN_VALUE"); DLR.LabelTarget breakLabel = DLR.Expression.Label(typeof(AType), "BREAK"); DLR.Expression result = DLR.Expression.Block( new DLR.ParameterExpression[] { returnValue }, // Assign the default return value: ANull DLR.Expression.Assign(returnValue, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Loop( DLR.Expression.Block( DLR.Expression.IfThen( // Test if the condition is equal to 0 // Invert the inner test's result DLR.Expression.Not( // This part will test if the condition is true (this means it is not 0) DLR.Expression.IsTrue( this.expression.Generate(scope), typeof(Helpers).GetMethod("BooleanTest") ) ), // Break out from the loop with the last computed value DLR.Expression.Break(breakLabel, returnValue) ), // Compute & assign the value DLR.Expression.Assign(returnValue, this.codeBlock.Generate(scope)) ), // The label where to jump in case of break breakLabel ) ); return(result); }
public override DLR.Expression Generate(AplusScope scope) { return Node.BuiltInFunction(this).Generate(scope); }
internal static DLR.Expression <Func <Aplus, AType> > BuildExecuteMethod( string sourceCode, Aplus environment ) { DLR.Expression codebody; // TODO: fix the third function info argument AplusCore.Compiler.AST.Node tree = Compiler.Parse.String(sourceCode, environment.LexerMode, null); AplusScope scope = new AplusScope(null, "__EVAL__", environment, DLR.Expression.Parameter(typeof(Aplus), "__EVAL_RUNTIME__"), DLR.Expression.Parameter(typeof(DYN.IDynamicMetaObjectProvider), "__EVAL_MODULE__"), //DLR.Expression.Parameter(typeof(Aplus), "__EVAL_ENVIRONMENT__"), DLR.Expression.Label(typeof(AType), "__EVAL_EXIT__"), isEval: true ); if (tree == null) { codebody = DLR.Expression.Constant(null); } else if (environment.FunctionScope != null) { AplusScope functionScope = new AplusScope(scope, "__EVAL_IN_FUNCTION__", moduleParam: DLR.Expression.Parameter(typeof(DYN.ExpandoObject), "__EVAL_FUNCTION_SCOPE__"), returnTarget: scope.ReturnTarget, isMethod: true ); codebody = DLR.Expression.Block( new DLR.ParameterExpression[] { //scope.RuntimeExpression, // runtime scope.ModuleExpression, // root context functionScope.ModuleExpression // Function local scope }, //DLR.Expression.Assign( // scope.RuntimeExpression, scope.RuntimeExpression //), DLR.Expression.Assign( scope.ModuleExpression, DLR.Expression.PropertyOrField(scope.RuntimeExpression, "Context") ), DLR.Expression.Assign( functionScope.ModuleExpression, DLR.Expression.PropertyOrField(scope.RuntimeExpression, "FunctionScope") ), DLR.Expression.Label( scope.ReturnTarget, tree.Generate(functionScope) ) ); } else { codebody = DLR.Expression.Block( new DLR.ParameterExpression[] { //scope.RuntimeExpression, // runtime scope.ModuleExpression // root context }, //DLR.Expression.Assign( // scope.RuntimeExpression, scope.RuntimeExpression //), DLR.Expression.Assign( scope.ModuleExpression, DLR.Expression.PropertyOrField(scope.RuntimeExpression, "Context") ), DLR.Expression.Label( scope.ReturnTarget, tree.Generate(scope) ) ); } DLR.Expression <Func <Aplus, AType> > lambda = DLR.Expression.Lambda <Func <Aplus, AType> >( codebody, scope.GetRuntimeExpression() ); return(lambda); }
public override DLR.Expression Generate(AplusScope scope) { // TODO: Add usage of Protected Execute Flag // Save the previous return target DLR.LabelTarget oldTarget = scope.ReturnTarget; scope.ReturnTarget = DLR.Expression.Label(typeof(AType), "EXIT"); DLR.Expression protectedCode = DLR.Expression.Label( scope.ReturnTarget, this.codeblock.Generate(scope) ); // Restore the return target; scope.ReturnTarget = oldTarget; // Code block contining the strandard execution's result // wrapped in a strand DLR.Expression block = DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), // We need to pass in reverse order protectedCode, DLR.Expression.Constant(AInteger.Create(0), typeof(AType)) ) ); // Parameter for Catch block DLR.ParameterExpression errorVariable = DLR.Expression.Parameter(typeof(Error), "error"); // Catch block, returns the ([errorcode]; [errortext]) strand DLR.CatchBlock catchBlock = DLR.Expression.Catch( errorVariable, DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), // We need to pass in reverse order // Error Text DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildString"), DLR.Expression.Property(errorVariable, "ErrorText") ), // Error Code DLR.Expression.Call( typeof(AInteger).GetMethod("Create", new Type[] { typeof(int) }), DLR.Expression.Convert( DLR.Expression.Property(errorVariable, "ErrorType"), typeof(int) ) ) ) ) ); DLR.Expression result = DLR.Expression.TryCatch( block, catchBlock ); return(result); }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); LinkedList<DLR.Expression> result = new LinkedList<DLR.Expression>(); DLR.ParameterExpression scalar = DLR.Expression.Parameter(typeof(AType), "_ScalarResult_"); DLR.ParameterExpression counter = DLR.Expression.Parameter(typeof(int), "COUNTER"); DLR.ParameterExpression exitValue = DLR.Expression.Parameter(typeof(int), "EXITVALUE"); DLR.LabelTarget exitLabel = DLR.Expression.Label(typeof(AType), "EXIT"); DLR.ParameterExpression returnValue = DLR.Expression.Parameter(typeof(AType), "RETURN"); bool incrementMode = true; if (this.expression is MonadicFunction && ((MonadicFunction)this.expression).Token.Type == Tokens.EXPONENTIAL) { // Change the counter's 'way' incrementMode = false; // Remove the Exponential function this.expression = ((MonadicFunction)this.expression).Expression; } if (this.expression is Assign && ((Assign)this.expression).Target is Identifier) { scope.IsAssignment = true; result.AddFirst(this.expression.Generate(scope)); scope.IsAssignment = false; // Remove the assignment and leave the identifier only this.expression = ((Assign)this.expression).Target; } // Save the previous return target DLR.LabelTarget oldTarget = scope.ReturnTarget; // Add an return target for the scope // this will allow the usage of the Result monadic function scope.ReturnTarget = exitLabel; if (this.expression is Identifier) { // Found a case like: VAR do { ... } Identifier variable = (Identifier)this.expression; // Generate a .Dynamic.Get DLR tree (used multiple times so this saves time) DLR.Expression variableGenerated = variable.Generate(scope); DLR.Expression variableAsFloat = DLR.Expression.Property(scalar, "asFloat"); result.AddLast(DLR.Expression.Block( new DLR.ParameterExpression[] { counter, exitValue, returnValue, scalar }, // Test if the constant is an integer DomainTest(variableGenerated, scalar), DLR.Expression.Assign(exitValue, (incrementMode ? // EXITVALUE = round(variable.asFloat) (DLR.Expression)FloatRounding(variableAsFloat) : // EXITVALUE = 0 (DLR.Expression)DLR.Expression.Constant(0, typeof(int)) ) ), DLR.Expression.Assign( counter, (incrementMode ? (DLR.Expression)DLR.Expression.Constant(0, typeof(int)) : (DLR.Expression)DLR.Expression.Decrement(FloatRounding(variableAsFloat)) ) ), // Start the loop DLR.Expression.Loop( DLR.Expression.Block( AST.Assign.GenerateIdentifierAssign( scope, variable, DLR.Expression.Call(typeof(LocalAInteger).GetMethod("Create"), counter), false, false ), DLR.Expression.IfThen( (incrementMode ? // Check if variable >= EXITVALUE is true DLR.Expression.GreaterThanOrEqual( counter, //DLR.Expression.Property(variableGenerated, "asInteger"), exitValue ) : // Check if EXITVALUE(0) > variable is true DLR.Expression.GreaterThan( exitValue, //DLR.Expression.Property(variableGenerated, "asInteger") counter ) ), // The expression was true, exit from the loop with the last value of the expression block DLR.Expression.Break(exitLabel, returnValue) ), // Otherwise run the inner codeblock DLR.Expression.Assign(returnValue, this.codeblock.Generate(scope)), // Update counter (incrementMode ? // ++counter DLR.Expression.PreIncrementAssign(counter) : // --counter DLR.Expression.PreDecrementAssign(counter) ) ), exitLabel ) )); } else { // Simple Iteration DLR.ParameterExpression temp = DLR.Expression.Parameter(typeof(AType), "TMP"); result.AddLast(DLR.Expression.Block( new DLR.ParameterExpression[] { temp, counter, exitValue, returnValue, scalar }, // Save the iteration count into a temporaly variable DLR.Expression.Assign(temp, this.expression.Generate(scope)), // Test if the constant is an integer DomainTest(temp, scalar), // MAXVALUE = temp.asInteger DLR.Expression.Assign(exitValue, FloatRounding(DLR.Expression.Property(scalar, "asFloat"))), // counter = 0 DLR.Expression.Assign(counter, DLR.Expression.Constant(0, typeof(int))), // Start the loop DLR.Expression.Loop( DLR.Expression.Block( // Check if counter >= MAXVALUE is true DLR.Expression.IfThen( DLR.Expression.GreaterThanOrEqual(counter, exitValue), // The expression was true, exit from the loop with the last calculated value DLR.Expression.Break(exitLabel, returnValue) ), // Otherwise run the inner codeblock, save the block's result DLR.Expression.Assign(returnValue, this.codeblock.Generate(scope)), // Increment the counter DLR.Expression.PreIncrementAssign(counter) ), exitLabel ) )); } // Restore the return target scope.ReturnTarget = oldTarget; return DLR.Expression.Block(result); }
/// <summary> /// Generate the DLR expression tree for the AST node /// </summary> /// <param name="scope"></param> /// <returns>DLR expression tree</returns> public virtual DLR.Expression Generate(AplusScope scope) { throw new NotImplementedException("Should !NEVER! reach this point. If this shown, then not all AST Nodes overridden this method!"); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (scope.IsAssignment && TokenUtils.AllowedPrimitiveFunction(this.token.Type)) { /* * input: y -> left side, x -> right side, value * Perform the function like this: * * i := f{y; iota rho x} * (,x)[i] := value * * where 'f' is the dyadic function */ DLR.Expression left = this.leftExpression.Generate(scope); DLR.Expression right = Node.TestMonadicToken(this.rightExpression, Tokens.RAVEL) ? ((MonadicFunction)this.rightExpression).Expression.Generate(scope) : this.rightExpression.Generate(scope) ; // i:=(iota rho x) DLR.Expression indices = AST.Assign.BuildIndicesList(scope, right); // (,x)[f{a;i}] result = AST.Assign.BuildIndexing(scope, right, GenerateDyadic(scope, indices, left)); } else if (scope.IsAssignment && this.token.Type == Tokens.CHOOSE) { scope.IsAssignment = false; DLR.Expression left = this.leftExpression.Generate(scope); scope.IsAssignment = true; DLR.Expression right = this.rightExpression.Generate(scope); result = DLR.Expression.Block( DLR.Expression.Assign(scope.CallbackInfo.Index, left), DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Choose), DyadicFunctionInstance.Choose.GetType().GetMethod("Assign"), right, left, scope.GetRuntimeExpression() ) ); } else if (scope.IsAssignment && this.token.Type == Tokens.PICK) { scope.IsAssignment = false; DLR.Expression left = this.leftExpression.Generate(scope); scope.IsAssignment = true; DLR.Expression right = this.rightExpression.Generate(scope); result = DLR.Expression.Block( DLR.Expression.Assign(scope.CallbackInfo.Path, left), DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Pick), DyadicFunctionInstance.Pick.GetType().GetMethod("Execute"), right, left, scope.GetRuntimeExpression() ) ); } else { DLR.Expression left = this.leftExpression.Generate(scope); DLR.Expression right = this.rightExpression.Generate(scope); result = GenerateDyadic(scope, right, left); } return result; }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression func, result; if (this.function is Token) { Node wrappedFunction = new BuiltInFunction((Token)this.function); func = wrappedFunction.Generate(scope); } else { func = this.function.Generate(scope); } DLR.ParameterExpression environment = scope.GetRuntimeExpression(); DLR.ParameterExpression functionParam = DLR.Expression.Variable(typeof(AType), "$$functionParam"); DLR.ParameterExpression rightParam = DLR.Expression.Variable(typeof(AType), "$$rightParam"); DLR.ParameterExpression valueParam = DLR.Expression.Variable(typeof(AType), "$$valueParam"); // TODO: rewrite this if (this.IsGeneralApply) { ExpressionList argumnets = (ExpressionList)this.rightarg; LinkedList <DLR.Expression> callArguments = new LinkedList <DLR.Expression>(); // 2. Add the parameters in !reverse! order foreach (Node item in argumnets.Items) { callArguments.AddFirst(item.Generate(scope)); } // 0. Add A+ environment as first argument for user defined functions callArguments.AddFirst(environment); // 1. Construct the method body callArguments.AddFirst(functionParam.Property("NestedItem")); result = DLR.Expression.Block( new DLR.ParameterExpression[] { functionParam, valueParam }, DLR.Expression.Assign(functionParam, func), DLR.Expression.IfThenElse( DLR.Expression.PropertyOrField(functionParam, "IsFunctionScalar"), DLR.Expression.Assign( valueParam, AST.UserDefInvoke.BuildInvoke(scope.GetRuntime(), callArguments) ), DLR.Expression.Throw( DLR.Expression.New( typeof(Error.Valence).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Constant("apply") ) ) ), valueParam ); } else if (isDyadic) { DLR.Expression right = this.rightarg.Generate(scope); DLR.Expression left = this.leftarg.Generate(scope); DLR.ParameterExpression leftParam = DLR.Expression.Variable(typeof(AType), "$$leftParam"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { functionParam, rightParam, leftParam, valueParam }, DLR.Expression.Assign(functionParam, func), DLR.Expression.Assign(rightParam, right), DLR.Expression.Assign(leftParam, left), DLR.Expression.IfThenElse( DLR.Expression.IsTrue( DLR.Expression.PropertyOrField(functionParam, "IsFunctionScalar") ), DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicOperatorInstance.Apply), DyadicOperatorInstance.Apply.GetType().GetMethod("Execute"), functionParam, rightParam, leftParam, environment ) ), DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicOperatorInstance.Each), DyadicOperatorInstance.Each.GetType().GetMethod("Execute"), functionParam, rightParam, leftParam, environment ) ) ), valueParam ); } else { DLR.Expression right = this.rightarg.Generate(scope); result = DLR.Expression.Block( new DLR.ParameterExpression[] { functionParam, rightParam, valueParam }, DLR.Expression.Assign(functionParam, func), DLR.Expression.Assign(rightParam, right), DLR.Expression.IfThenElse( DLR.Expression.IsTrue( DLR.Expression.PropertyOrField(functionParam, "IsFunctionScalar") ), DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Apply), MonadicOperatorInstance.Apply.GetType().GetMethod("Execute"), functionParam, rightParam, environment ) ), DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Each), MonadicOperatorInstance.Each.GetType().GetMethod("Execute"), functionParam, rightParam, environment ) ) ), valueParam ); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); if (scope.IsEval && scope.IsMethod) { // we are inside a function and an eval block. // override the original eval scope // create a top level scope scope = new AplusScope(null, "_EVAL_FUNC_SCOPE_", scope.GetRuntime(), scope.GetRuntimeExpression(), scope.Parent.GetModuleExpression(), scope.ReturnTarget, isEval: true ); } string methodName = this.name.BuildQualifiedName(runtime.CurrentContext); // 1. Create a new scope for the function string scopename = String.Format("__method_{0}_scope__", this.name.Name); AplusScope methodScope = new AplusScope(scope, scopename, runtimeParam: DLR.Expression.Parameter(typeof(Aplus), "_EXTERNAL_RUNTIME_"), moduleParam: DLR.Expression.Parameter(typeof(DYN.ExpandoObject), scopename), returnTarget: DLR.Expression.Label(typeof(AType), "RETURN"), isMethod: true ); // 1.5 Create a result parameter DLR.ParameterExpression resultParameter = DLR.Expression.Parameter(typeof(AType), "__RESULT__"); // 2. Create function's parameters LinkedList <DLR.ParameterExpression> methodParameters = new LinkedList <DLR.ParameterExpression>(); foreach (Node parameter in this.parameters.Items) { string parameterName = ((Identifier)parameter).Name; DLR.ParameterExpression parameterExpression = DLR.Expression.Parameter(typeof(AType), parameterName); // Add parameter to the scope's variable list methodScope.Variables[parameterName] = parameterExpression; // Add parameters in !reverse! order methodParameters.AddFirst(parameterExpression); } // Add parameter for AplusEnviroment methodParameters.AddFirst(methodScope.RuntimeExpression); // Create a return label for exiting from the function //methodScope.ReturnTarget = ; // 3. Create the lambda method for the function DLR.LambdaExpression method = DLR.Expression.Lambda( DLR.Expression.Block( new DLR.ParameterExpression[] { methodScope.ModuleExpression, resultParameter }, // Add the local scope's store DLR.Expression.Assign(methodScope.ModuleExpression, DLR.Expression.Constant(new DYN.ExpandoObject())), // set AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), methodScope.ModuleExpression ), // Calculate the result of the defined function DLR.Expression.Assign( resultParameter, DLR.Expression.Label(methodScope.ReturnTarget, this.codeblock.Generate(methodScope)) ), // reset AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), DLR.Expression.Constant(null, typeof(DYN.ExpandoObject)) ), // Return the result resultParameter ), methodName, methodParameters ); // 3.5. Wrap the lambda method inside an AFunc DLR.Expression wrappedLambda = DLR.Expression.Call( typeof(AFunc).GetMethod("Create", new Type[] { typeof(string), typeof(object), typeof(int), typeof(string) }), DLR.Expression.Constant(methodName), method, DLR.Expression.Constant(methodParameters.Count), DLR.Expression.Constant(this.code) ); // 4. Set the variable to the lambda function DLR.Expression setMethod = VariableHelper.SetVariable( runtime, scope.ModuleExpression, this.name.CreateContextNames(runtime.CurrentContext), wrappedLambda ); // ensure the result type to be an AType DLR.Expression result = DLR.Expression.Convert(setMethod, typeof(AType)); return(result); }
/// <summary> /// Builds DLR expression for: (iota rho argument) /// </summary> /// <param name="scope"></param> /// <param name="argument"></param> /// <returns></returns> internal static DLR.Expression BuildIndicesList(AplusScope scope, DLR.Expression argument) { DLR.ParameterExpression environment = scope.GetRuntimeExpression(); var execute = typeof(AbstractMonadicFunction).GetMethod("Execute"); // (iota rho x) DLR.Expression indexes = DLR.Expression.Call( DLR.Expression.Constant(MonadicFunctionInstance.Interval), execute, DLR.Expression.Call( DLR.Expression.Constant(MonadicFunctionInstance.Shape), execute, argument, environment ), environment ); return indexes; }
internal static DLR.Expression BuildPresetCallbackCall(AplusScope scope, DLR.ParameterExpression valueParam) { DLR.ParameterExpression callbackParameter = DLR.Expression.Parameter(typeof(CallbackItem), "__CALLBACK__"); DLR.Expression callback = DLR.Expression.Block( new DLR.ParameterExpression[] { callbackParameter }, DLR.Expression.Condition( DLR.Expression.Call( scope.GetRuntimeExpression().Property("CallbackManager"), typeof(CallbackManager).GetMethod("TryGetPresetCallback"), scope.CallbackInfo.QualifiedName, callbackParameter ), DLR.Expression.Dynamic( // TODO: do not instantiate the binder here new Runtime.Binder.CallbackBinder(), typeof(object), callbackParameter, scope.GetRuntimeExpression(), valueParam, scope.CallbackInfo.Index, scope.CallbackInfo.Path ).To<AType>(), (DLR.Expression)valueParam.To<AType>() ) ); return callback; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); // arguments for the dynamic method call LinkedList <DLR.Expression> callArguments = new LinkedList <DLR.Expression>(); if (scope.IsAssignment) { // Generate the paramters differently for assignment // f{...;x} := value <=> i := f{...; iota rho x}; (,x)[i] := value List <Node> items = new List <Node>(this.arguments.Items); // 2. Add the parameters in !reverse! order except the last one for (int i = 0; i < items.Count - 1; i++) { callArguments.AddFirst(items[i].Generate(scope)); } Node lastItem = items[items.Count - 1]; bool isPick = Node.TestDyadicToken(lastItem, Grammar.Tokens.PICK); bool isRavel = Node.TestMonadicToken(lastItem, Grammar.Tokens.RAVEL); if (!(lastItem is Identifier || isPick || isRavel)) { throw new ParseException("user-def invoke assign", false); } DLR.Expression indexList = AST.Assign.BuildIndicesList(scope, lastItem.Generate(scope)); callArguments.AddFirst(indexList); } else { // 2. Add the parameters in !reverse! order foreach (Node item in this.arguments.Items) { callArguments.AddFirst(item.Generate(scope)); } } // 0. Add A+ environment as first argument for user defined functions callArguments.AddFirst(scope.GetRuntimeExpression()); // 1. Construct the method body callArguments.AddFirst(this.method.Generate(scope)); DLR.Expression result; if (scope.IsAssignment) { // (,x)[f{...;iota rho x}] result = AST.Assign.BuildIndexing( scope, this.arguments.Items.Last.Value.Generate(scope), BuildInvoke(runtime, callArguments) ); } else { // 3. Dynamic invoke of method // Order of arguments: // (method, Enviroment, argN, ... arg1, arg0) result = BuildInvoke(runtime, callArguments); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (this.nodeList.Count > 0) { result = DLR.Expression.Block(this.nodeList.Select(node => node.Generate(scope))); } else { result = DLR.Expression.Constant(Utils.ANull()); } return result; }
public override DLR.Expression Generate(AplusScope scope) { return(Node.BuiltInFunction(this).Generate(scope)); }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); LinkedList <DLR.Expression> result = new LinkedList <DLR.Expression>(); DLR.ParameterExpression scalar = DLR.Expression.Parameter(typeof(AType), "_ScalarResult_"); DLR.ParameterExpression counter = DLR.Expression.Parameter(typeof(int), "COUNTER"); DLR.ParameterExpression exitValue = DLR.Expression.Parameter(typeof(int), "EXITVALUE"); DLR.LabelTarget exitLabel = DLR.Expression.Label(typeof(AType), "EXIT"); DLR.ParameterExpression returnValue = DLR.Expression.Parameter(typeof(AType), "RETURN"); bool incrementMode = true; if (this.expression is MonadicFunction && ((MonadicFunction)this.expression).Token.Type == Tokens.EXPONENTIAL) { // Change the counter's 'way' incrementMode = false; // Remove the Exponential function this.expression = ((MonadicFunction)this.expression).Expression; } if (this.expression is Assign && ((Assign)this.expression).Target is Identifier) { scope.IsAssignment = true; result.AddFirst(this.expression.Generate(scope)); scope.IsAssignment = false; // Remove the assignment and leave the identifier only this.expression = ((Assign)this.expression).Target; } // Save the previous return target DLR.LabelTarget oldTarget = scope.ReturnTarget; // Add an return target for the scope // this will allow the usage of the Result monadic function scope.ReturnTarget = exitLabel; if (this.expression is Identifier) { // Found a case like: VAR do { ... } Identifier variable = (Identifier)this.expression; // Generate a .Dynamic.Get DLR tree (used multiple times so this saves time) DLR.Expression variableGenerated = variable.Generate(scope); DLR.Expression variableAsFloat = DLR.Expression.Property(scalar, "asFloat"); result.AddLast(DLR.Expression.Block( new DLR.ParameterExpression[] { counter, exitValue, returnValue, scalar }, // Test if the constant is an integer DomainTest(variableGenerated, scalar), DLR.Expression.Assign(exitValue, (incrementMode ? // EXITVALUE = round(variable.asFloat) (DLR.Expression)FloatRounding(variableAsFloat) : // EXITVALUE = 0 (DLR.Expression)DLR.Expression.Constant(0, typeof(int)) ) ), DLR.Expression.Assign( counter, (incrementMode ? (DLR.Expression)DLR.Expression.Constant(0, typeof(int)) : (DLR.Expression)DLR.Expression.Decrement(FloatRounding(variableAsFloat)) ) ), // Start the loop DLR.Expression.Loop( DLR.Expression.Block( AST.Assign.GenerateIdentifierAssign( scope, variable, DLR.Expression.Call(typeof(LocalAInteger).GetMethod("Create"), counter), false, false ), DLR.Expression.IfThen( (incrementMode ? // Check if variable >= EXITVALUE is true DLR.Expression.GreaterThanOrEqual( counter, //DLR.Expression.Property(variableGenerated, "asInteger"), exitValue ) : // Check if EXITVALUE(0) > variable is true DLR.Expression.GreaterThan( exitValue, //DLR.Expression.Property(variableGenerated, "asInteger") counter ) ), // The expression was true, exit from the loop with the last value of the expression block DLR.Expression.Break(exitLabel, returnValue) ), // Otherwise run the inner codeblock DLR.Expression.Assign(returnValue, this.codeblock.Generate(scope)), // Update counter (incrementMode ? // ++counter DLR.Expression.PreIncrementAssign(counter) : // --counter DLR.Expression.PreDecrementAssign(counter) ) ), exitLabel ) )); } else { // Simple Iteration DLR.ParameterExpression temp = DLR.Expression.Parameter(typeof(AType), "TMP"); result.AddLast(DLR.Expression.Block( new DLR.ParameterExpression[] { temp, counter, exitValue, returnValue, scalar }, // Save the iteration count into a temporaly variable DLR.Expression.Assign(temp, this.expression.Generate(scope)), // Test if the constant is an integer DomainTest(temp, scalar), // MAXVALUE = temp.asInteger DLR.Expression.Assign(exitValue, FloatRounding(DLR.Expression.Property(scalar, "asFloat"))), // counter = 0 DLR.Expression.Assign(counter, DLR.Expression.Constant(0, typeof(int))), // Start the loop DLR.Expression.Loop( DLR.Expression.Block( // Check if counter >= MAXVALUE is true DLR.Expression.IfThen( DLR.Expression.GreaterThanOrEqual(counter, exitValue), // The expression was true, exit from the loop with the last calculated value DLR.Expression.Break(exitLabel, returnValue) ), // Otherwise run the inner codeblock, save the block's result DLR.Expression.Assign(returnValue, this.codeblock.Generate(scope)), // Increment the counter DLR.Expression.PreIncrementAssign(counter) ), exitLabel ) )); } // Restore the return target scope.ReturnTarget = oldTarget; return(DLR.Expression.Block(result)); }
private DLR.Expression GenerateDyadic(AplusScope scope, DLR.Expression right, DLR.Expression left) { DLR.Expression result; DLR.ParameterExpression environment = scope.GetRuntimeExpression(); if (this.token.Type == Tokens.OR) { DLR.ParameterExpression leftParam = DLR.Expression.Variable(typeof(AType), "$$leftParam"); DLR.ParameterExpression rightParam = DLR.Expression.Variable(typeof(AType), "$$rightParam"); DLR.ParameterExpression valueParam = DLR.Expression.Variable(typeof(AType), "$$valueParam"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { leftParam, rightParam, valueParam }, DLR.Expression.Assign(rightParam, right), DLR.Expression.Assign(leftParam, left), DLR.Expression.IfThenElse( // $left.IsNumber || ($left.Type == ATypes.ANull) DLR.Expression.OrElse( DLR.Expression.IsTrue( DLR.Expression.PropertyOrField(leftParam, "IsNumber") ), DLR.Expression.Equal( DLR.Expression.PropertyOrField(leftParam, "Type"), DLR.Expression.Constant(ATypes.ANull) ) ), // Or($right, $left) DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Or), DyadicFunctionInstance.Or.GetType().GetMethod("Execute"), rightParam, leftParam, environment ) ), // Cast($right, $left) DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Cast), DyadicFunctionInstance.Cast.GetType().GetMethod("Execute"), rightParam, leftParam, environment ) ) ), valueParam ); } else if (this.token.Type == Tokens.BWOR) { DLR.ParameterExpression rightParam = DLR.Expression.Variable(typeof(AType), "$$rightParam"); DLR.ParameterExpression leftParam = DLR.Expression.Variable(typeof(AType), "$$leftParam"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { leftParam, rightParam }, DLR.Expression.Assign(rightParam, right), DLR.Expression.Assign(leftParam, left), DLR.Expression.Condition( // $left.Type == ATypes.ASymbol DLR.Expression.Equal( leftParam.Property("Type"), DLR.Expression.Constant(ATypes.ASymbol) ), DLR.Expression.Constant(DyadicFunctionInstance.BitwiseCast).Call<BitwiseCast>( "Execute", rightParam, leftParam, environment ), DLR.Expression.Constant(DyadicFunctionInstance.BitwiseOr).Call<BitwiseOr>( "Execute", rightParam, leftParam, environment ) ) ); } else { AbstractDyadicFunction method = MethodChooser.GetDyadicMethod(this.token); if (method == null) { throw new ParseException(String.Format("Not supported Dyadic function[{0}]", this.token)); } result = DLR.Expression.Call( DLR.Expression.Constant(method), method.GetType().GetMethod("Execute"), right, left, environment ); } return result; }
internal static DLR.Expression GenerateIdentifierAssign( AplusScope scope, Identifier target, DLR.Expression value, bool isStrand = false, bool needCallback = true) { Aplus runtime = scope.GetRuntime(); DLR.Expression result = null; if (scope.IsMethod) { string qualifiedName = target.BuildQualifiedName(runtime.CurrentContext); // If the generation is inside of a method // check if it has the variablename as function parameter DLR.Expression functionParameter = scope.FindIdentifier(target.Name); if (functionParameter != null) { // Found variable as a function parameter, do a simple assign // the variable is already defined in AST.UserDefFunction return DLR.Expression.Assign(functionParameter, value); } DLR.Expression functionScopeParam = scope.GetModuleExpression(); DLR.Expression globalScopeParam = scope.Parent.GetModuleExpression(); switch (target.Type) { case IdentifierType.UnQualifiedName: // Need to check if we are inside an eval block: if (scope.IsEval) { // Code is inside an eval block, we behave slightly differently! #region description about what are we doing in this case // // Check if the variable exists in the function's scope // |-> Exists: set that variable's value // |-> otherwise: set the global variable's value // // if(((IDictionary<String, Object>)($FunctionScope).ContainsKey($VARIABLE)) // { // $FunctionScope.$VARIABLE = $VALUE; // } // else // { // $GlobalScope.$VARIABLE = $VALUE; // } // #endregion result = DLR.Expression.Condition( // Check if the varaible exists in the function scope DLR.Expression.Call( DLR.Expression.Convert(functionScopeParam, typeof(IDictionary<string, object>)), typeof(IDictionary<string, object>).GetMethod("ContainsKey"), DLR.Expression.Constant(target.Name) ), // found the variable in function scope, so assign a value to it DLR.Expression.Block( needCallback ? DLR.Expression.Assign(scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName)) : (DLR.Expression)DLR.Expression.Empty(), DLR.Expression.Dynamic( runtime.SetMemberBinder(target.Name), typeof(object), functionScopeParam, value ), value ), // did NOT found the variable in the function scope // perform the assignment in the global scope BuildGlobalAssignment(scope, runtime, globalScopeParam, target, value, isStrand, needCallback) ); } else if (target.IsEnclosed) { result = BuildGlobalAssignment(scope, runtime, globalScopeParam, target, value, isStrand, needCallback); } else { // Simple case, we are inside a user defined function, but not inside an eval block result = DLR.Expression.Block( needCallback ? DLR.Expression.Assign(scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName)) : (DLR.Expression)DLR.Expression.Empty(), DLR.Expression.Dynamic( runtime.SetMemberBinder(target.Name), typeof(object), functionScopeParam, value ) ); } break; case IdentifierType.QualifiedName: case IdentifierType.SystemName: default: // Do an assignment on the global scope result = BuildGlobalAssignment(scope, runtime, globalScopeParam, target, value, isStrand, needCallback); break; } } else { result = BuildGlobalAssignment(scope, runtime, scope.GetModuleExpression(), target, value, isStrand, needCallback); } return DLR.Expression.Convert(result, typeof(AType)); }
private DLR.Expression BuildGlobalAccessor( AplusScope scope, Aplus runtime, DLR.Expression variableContainer, string[] contextParts) { DLR.ParameterExpression environment = scope.GetRuntimeExpression(); DLR.Expression name = DLR.Expression.Constant(BuildQualifiedName(runtime.CurrentContext)); DLR.Expression dependencyManager = DLR.Expression.Property(scope.GetRuntimeExpression(), "DependencyManager"); // Build the ET for getting the dependecy for the variable DLR.Expression dependencyInformation = DLR.Expression.Call( dependencyManager, typeof(DependencyManager).GetMethod("GetDependency"), name ); // Build the ET for invoking the dependecy. DLR.Expression dependencyEvaulate = DLR.Expression.Condition( dependencyInformation.Property("IsItemwise"), AST.UserDefInvoke.BuildInvoke( runtime, new DLR.Expression[] { dependencyInformation.Property("Function"), environment, dependencyInformation.Property("InvalidIndex") } ), AST.UserDefInvoke.BuildInvoke( runtime, new DLR.Expression[] { DLR.Expression.Property(dependencyInformation, "Function"), environment } ) ); /* * Simplified code of the resulting ET: * * result = $runtime.DependecyManager.IsInvalid($$variable) * ? { $$value = $runtime.DependencyManager.GetDependency($$name).Function() * path, index = Utils.ANull(); * $$nonPresetvalue = $$value.IsMemoryMappedFile ? $$value : $$value.Clone(); * $$qualifiedName = qualifiedname; * $$value = presetCallback($$value); * $$variable = $$value * $$nonPresetvalue * : $$variable */ DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); DLR.ParameterExpression value = DLR.Expression.Parameter(typeof(AType)); DLR.Expression callback = AST.Assign.BuildCallbackCall(scope, value); DLR.Expression presetCallback = AST.Assign.BuildPresetCallbackCall(scope, value); string qualifiedName = this.BuildQualifiedName(scope.GetRuntime().CurrentContext); DLR.Expression temp = DLR.Expression.Block( new DLR.ParameterExpression[] { value }, DLR.Expression.Condition( DLR.Expression.Call( dependencyManager, typeof(DependencyManager).GetMethod("IsInvalid"), name ), DLR.Expression.Block( new DLR.ParameterExpression[] { scope.CallbackInfo.QualifiedName, scope.CallbackInfo.NonPresetValue, scope.CallbackInfo.Path, scope.CallbackInfo.Index }, DLR.Expression.Assign(value, dependencyEvaulate), DLR.Expression.Assign(scope.CallbackInfo.Path, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Assign(scope.CallbackInfo.Index, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Assign( scope.CallbackInfo.NonPresetValue, DLR.Expression.Condition( DLR.Expression.Property(value, "IsMemoryMappedFile"), value, DLR.Expression.Call( value, typeof(AType).GetMethod("Clone") ) ) ), DLR.Expression.Assign( scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName) ), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), VariableHelper.SetVariable( runtime, variableContainer, contextParts, value ), scope.CallbackInfo.NonPresetValue ), VariableHelper.GetVariable( runtime, variableContainer, contextParts ), typeof(object) ) ).ToAType(runtime); DLR.Expression result = temp; if (scope.IsAssignment) { result = DLR.Expression.Block( DLR.Expression.Assign( scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName) ), temp ); } return(result); }
private static DLR.Expression GenerateOpFunction(AplusScope scope, Operator op) { DLR.Expression function; if (op.isBuiltin) { function = AST.Node.BuiltInFunction((Token)op.Function).Generate(scope); } else { function = op.Function.Generate(scope); } return function; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); if (scope.IsEval && scope.IsMethod) { // we are inside a function and an eval block. // override the original eval scope // create a top level scope scope = new AplusScope(null, "_EVAL_FUNC_SCOPE_", scope.GetRuntime(), scope.GetRuntimeExpression(), scope.Parent.GetModuleExpression(), scope.ReturnTarget, isEval: true ); } string operatorName = this.name.BuildQualifiedName(runtime.CurrentContext); string scopename = String.Format("__operator_{0}_scope__", this.name.Name); AplusScope methodScope = new AplusScope(scope, scopename, runtimeParam: DLR.Expression.Parameter(typeof(Aplus), "_EXTERNAL_RUNTIME_"), moduleParam: DLR.Expression.Parameter(typeof(DYN.ExpandoObject), scopename), returnTarget: DLR.Expression.Label(typeof(AType), "RETURN"), isMethod: true ); // create a result parameter DLR.ParameterExpression resultParameter = DLR.Expression.Parameter(typeof(AType), "__RESULT__"); // create function's parameters LinkedList <DLR.ParameterExpression> methodParameters = new LinkedList <DLR.ParameterExpression>(); // add parameters to the linkedlist BuildParameterExpression(methodScope, methodParameters, leftArgument); BuildParameterExpression(methodScope, methodParameters, function); BuildParameterExpression(methodScope, methodParameters, condition); BuildParameterExpression(methodScope, methodParameters, rightArgument); // add parameter for AplusEnviroment methodParameters.AddFirst(methodScope.RuntimeExpression); // create the lambda method for the function DLR.LambdaExpression method = DLR.Expression.Lambda( DLR.Expression.Block( new DLR.ParameterExpression[] { methodScope.ModuleExpression, resultParameter }, // add the local scope's store DLR.Expression.Assign(methodScope.ModuleExpression, DLR.Expression.Constant(new DYN.ExpandoObject())), // set AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), methodScope.ModuleExpression ), // calculate the result of the defined function DLR.Expression.Assign( resultParameter, DLR.Expression.Label(methodScope.ReturnTarget, this.codeblock.Generate(methodScope)) ), // reset AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), DLR.Expression.Constant(null, typeof(DYN.ExpandoObject)) ), // return the result resultParameter ), operatorName, methodParameters ); // wrap the lambda method inside an AFunc DLR.Expression wrappedLambda = DLR.Expression.Call( typeof(AFunc).GetMethod("CreateUserOperator"), DLR.Expression.Constant(operatorName), DLR.Expression.Constant(this.IsDyadicOperator), method, DLR.Expression.Constant(methodParameters.Count), DLR.Expression.Constant(this.codeText) ); // set the variable to the lambda function DLR.Expression setMethod = VariableHelper.SetVariable( runtime, scope.ModuleExpression, this.name.CreateContextNames(runtime.CurrentContext), wrappedLambda ); // ensure the result type to be an AType DLR.Expression result = DLR.Expression.Convert(setMethod, typeof(AType)); return(result); }
public override DLR.Expression Generate(AplusScope scope) { PreprocessVariables(scope); DLR.Expression result = null; Aplus runtime = scope.GetRuntime(); if (scope.IsEval && scope.IsMethod) { // override the original scope // create a top level scope scope = new AplusScope(null, "_EVAL_DEP_SCOPE_", scope.GetRuntime(), scope.GetRuntimeExpression(), scope.Parent.GetModuleExpression(), scope.ReturnTarget, isEval: true ); } // 1. Create a function scope string dependencyName = this.variable.BuildQualifiedName(runtime.CurrentContext); string scopename = String.Format("__dependency_{0}_scope__", this.variable.Name); AplusScope dependencyScope = new AplusScope(scope, scopename, runtimeParam: scope.GetRuntimeExpression(), moduleParam: DLR.Expression.Parameter(typeof(DYN.ExpandoObject), scopename), returnTarget: DLR.Expression.Label(typeof(AType), "RETURN"), isMethod: true ); // 1.5. Method for registering dependencies MethodInfo registerMethod; // 2. Prepare the method arguments (RuntimeExpression) DLR.ParameterExpression[] methodParameters; if (this.IsItemwise) { DLR.ParameterExpression index = DLR.Expression.Parameter(typeof(AType), string.Format("__INDEX[{0}]__", this.Indexer.Name)); dependencyScope.Variables.Add(this.Indexer.Name, index); methodParameters = new DLR.ParameterExpression[] { dependencyScope.RuntimeExpression, index }; registerMethod = typeof(DependencyManager).GetMethod("RegisterItemwise"); } else { methodParameters = new DLR.ParameterExpression[] { dependencyScope.RuntimeExpression }; registerMethod = typeof(DependencyManager).GetMethod("Register"); } // 2.5 Create a result parameter DLR.ParameterExpression resultParameter = DLR.Expression.Parameter(typeof(AType), "__RESULT__"); // 2.75 Get the dependency informations DLR.Expression dependencyInformation = DLR.Expression.Call( DLR.Expression.Property(dependencyScope.GetRuntimeExpression(), "DependencyManager"), typeof(DependencyManager).GetMethod("GetDependency"), DLR.Expression.Constant(dependencyName) ); // 3. Build the method DLR.LambdaExpression method = DLR.Expression.Lambda( DLR.Expression.Block( new DLR.ParameterExpression[] { dependencyScope.ModuleExpression, resultParameter }, // Add the local scope's store DLR.Expression.Assign(dependencyScope.ModuleExpression, DLR.Expression.Constant(new DYN.ExpandoObject())), // set AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(dependencyScope.RuntimeExpression, "FunctionScope"), dependencyScope.ModuleExpression ), // Mark the dependency as under evaluation DLR.Expression.Call( dependencyInformation, typeof(DependencyItem).GetMethod("Mark"), DLR.Expression.Constant(DependencyState.Evaluating) ), // Calculate the result of the defined function DLR.Expression.Assign( resultParameter, DLR.Expression.Label(dependencyScope.ReturnTarget, this.functionBody.Generate(dependencyScope)) ), // Mark the dependency as valid DLR.Expression.Call( dependencyInformation, typeof(DependencyItem).GetMethod("Mark"), DLR.Expression.Constant(DependencyState.Valid) ), // reset AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(dependencyScope.RuntimeExpression, "FunctionScope"), DLR.Expression.Constant(null, typeof(DYN.ExpandoObject)) ), // Return the result resultParameter ), dependencyName, methodParameters ); DLR.Expression wrappedLambda = DLR.Expression.Call( typeof(AFunc).GetMethod("Create"), DLR.Expression.Constant(dependencyName), method, DLR.Expression.Constant(methodParameters.Length), DLR.Expression.Constant(this.codeText) ); // 3.5 Build dependant set // filter out the variables from the dependant set if it is a local variable HashSet <string> dependents = new HashSet <string>( from pair in this.variables.Accessing // get all variables where !this.variables.LocalAssignment.ContainsKey(pair.Key) // but skip the local variables select pair.Value[0].BuildQualifiedName(runtime.CurrentContext) // then build the correct name ); // 4. Register the method for the Dependency manager DLR.ParameterExpression dependencyMethodParam = DLR.Expression.Parameter(typeof(AType), "__DEP._METHOD__"); DLR.Expression dependencyManager = DLR.Expression.Property(scope.GetRuntimeExpression(), "DependencyManager"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { dependencyMethodParam }, DLR.Expression.Assign(dependencyMethodParam, wrappedLambda), DLR.Expression.Call( dependencyManager, registerMethod, DLR.Expression.Constant(dependencyName, typeof(string)), DLR.Expression.Constant(dependents, typeof(HashSet <string>)), dependencyMethodParam ), dependencyMethodParam ); return(result); }
private DLR.Expression BuildPickAssign(AplusScope scope, DLR.Expression value) { DyadicFunction function = (DyadicFunction)this.target; bool isValueinContext = Node.TestDyadicToken(function.Left, Grammar.Tokens.VALUEINCONTEXT); bool isValue = Node.TestMonadicToken(function.Right, Grammar.Tokens.VALUE); if (!(function.Right is Identifier || isValueinContext || isValue)) { throw new ParseException("assign pick target", false); } DLR.Expression left = function.Left.Generate(scope); scope.IsAssignment = true; DLR.Expression right = function.Right.Generate(scope); scope.IsAssignment = false; var method = DyadicFunctionInstance.Pick; DLR.Expression pickDLR = DLR.Expression.Call( DLR.Expression.Constant(method), method.GetType().GetMethod("AssignExecute"), right, left, scope.GetRuntimeExpression() ); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); var flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static; DLR.ParameterExpression temp = DLR.Expression.Parameter(typeof(AType)); DLR.Expression callback = BuildCallbackCall(scope, temp); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, temp); DLR.Expression result = DLR.Expression.Block( new DLR.ParameterExpression[] { temp }, DLR.Expression.Assign(scope.CallbackInfo.Path, left), DLR.Expression.Assign(temp, value), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(temp, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Call( typeof(Assign).GetMethod("PickAssignHelper", flags), temp, pickDLR ), callback ) ), scope.CallbackInfo.NonPresetValue ); return result; }
/// <summary> /// Generate the DLR expression tree for the AST node /// </summary> /// <param name="scope"></param> /// <returns>DLR expression tree</returns> public virtual DLR.Expression Generate(AplusScope scope) { throw new NotImplementedException("Should !NEVER! reach this point. If this shown, then not all AST Nodes overridden this method!"); }
/// <summary>Generates a DLR Expression for Strand assignment.</summary> /// <remarks> /// Transform this: /// (a;b;...) := ..... // don't care what is there :) /// /// to this in DLR: /// /// $__VALUES__ = (AType) .....; // ..... is a generated DLR expression now! /// /// if($__VALUES__.IsArray) // case A /// { /// if($VALUES.length != 2) // 2 the # of targets /// { /// throw new Error.Length("assign"); /// } /// /// a = disclose( ((AArray)$__VALUES__)[0] ); /// b = disclose( ((AArray)$__VALUES__)[1] ); /// ... /// } /// else // case B /// { /// // need to disclose the box /// if($__VALUES__.Type == ATypes.Box) /// { /// $__VALUES__ = disclose($__VALUES__); /// } /// a = $VALUES.Clone(); /// b = $VALUES.Clone(); /// ... /// } /// $__DependencyManager__.InvalidateDependencies(string[] { a,b, .. }) /// $__DependencyManager__.ValidateDependencies(string[] { a,b, .. }) /// </remarks> /// <param name="scope"></param> /// <param name="targets"> /// Strand containing Identifiers. /// If a node which in not an Identifier found, ParseException is thrown /// </param> /// <param name="value">The generated value which will be assigned to the targets</param> /// <returns>A generated DLR expression for strand assignment</returns> private static DLR.Expression GenerateStrandAssign(AplusScope scope, Strand targets, DLR.Expression value) { AbstractMonadicFunction disclose = MonadicFunctionInstance.Disclose; Aplus runtime = scope.GetRuntime(); DLR.ParameterExpression environment = scope.GetRuntimeExpression(); DLR.ParameterExpression valuesParam = DLR.Expression.Parameter(typeof(AType), "__VALUES__"); // for dependency evaluation List<string> targetVariables = new List<string>(); // for case A) assigns List<DLR.Expression> strand2StrandAssigns = new List<DLR.Expression>(); // for case B) assigns List<DLR.Expression> strand2ValueAssigns = new List<DLR.Expression>() { DLR.Expression.Assign( valuesParam, DLR.Expression.Call( DLR.Expression.Constant(disclose), disclose.GetType().GetMethod("Execute"), valuesParam, environment ) ) }; int indexCounter = 0; foreach (Node node in targets.Items) { if (!(node is Identifier)) { throw new ParseException("assign lhs"); } Identifier id = (Identifier)node; DLR.Expression strandValue = DLR.Expression.Call( DLR.Expression.Constant(disclose), disclose.GetType().GetMethod("Execute"), DLR.Expression.MakeIndex( valuesParam, typeof(AType).GetIndexerProperty(typeof(int)), // The indexer property which will be used new DLR.Expression[] { DLR.Expression.Constant(indexCounter, typeof(int)) } ), environment ); // case A) $TARGETS[i] = disclose($VALUES[i]) strand2StrandAssigns.Add(GenerateIdentifierAssign(scope, id, strandValue, isStrand: true)); // case B) $TARGETS[i] = $VALUE.Clone() strand2ValueAssigns.Add( GenerateIdentifierAssign( scope, id, DLR.Expression.Condition( DLR.Expression.Property(valuesParam, "IsMemoryMappedFile"), valuesParam, DLR.Expression.Call( valuesParam, typeof(AType).GetMethod("Clone") ) ), isStrand: true ) ); // gather the global variables for dependency validation/invalidation. if ((scope.IsMethod && id.IsEnclosed) || !scope.IsMethod) { targetVariables.Add(id.BuildQualifiedName(runtime.CurrentContext)); } indexCounter++; } // case A) DLR.Expression caseStrand2Strand = DLR.Expression.IfThenElse( DLR.Expression.NotEqual( DLR.Expression.PropertyOrField(valuesParam, "Length"), DLR.Expression.Constant(indexCounter, typeof(int)) ), DLR.Expression.Throw( DLR.Expression.New( typeof(Error.Length).GetConstructor(new Type[] { typeof(string) }), DLR.Expression.Constant("assign", typeof(string)) ) ), DLR.Expression.Block(strand2StrandAssigns) ); DLR.Expression dependencyManager = DLR.Expression.Property(scope.GetRuntimeExpression(), "DependencyManager"); DLR.Expression result = DLR.Expression.Block( new DLR.ParameterExpression[] { valuesParam }, DLR.Expression.Assign(valuesParam, DLR.Expression.Convert(value, typeof(AType))), DLR.Expression.IfThenElse( DLR.Expression.PropertyOrField(valuesParam, "IsArray"), // case A) caseStrand2Strand, // case B) DLR.Expression.Block(strand2ValueAssigns) ), DLR.Expression.Call( dependencyManager, typeof(DependencyManager).GetMethod("InvalidateDependencies", new Type[] { typeof(string[]) }), DLR.Expression.Constant(targetVariables.ToArray()) ), DLR.Expression.Call( dependencyManager, typeof(DependencyManager).GetMethod("ValidateDependencies"), DLR.Expression.Constant(targetVariables.ToArray()) ), valuesParam ); return DLR.Expression.Block(result, DLR.Expression.Assign(scope.CallbackInfo.NonPresetValue, value)); }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; Aplus runtime = scope.GetRuntime(); if (this.Type == IdentifierType.SystemName && runtime.SystemFunctions.ContainsKey(this.Name)) { // Check if the name is a system function's name and we have such system function // and return it result = DLR.Expression.Constant(runtime.SystemFunctions[this.Name]); return(result); } DLR.Expression variableContainer = scope.GetModuleExpression(); string[] contextParts = CreateContextNames(runtime.CurrentContext); // Check if the scope is a method if (scope.IsMethod) { DLR.Expression parentVariableContainer = scope.Parent.GetModuleExpression(); // Check for variable in method scope // (maybe the variable is defined in the method header) DLR.Expression localVariable = scope.FindIdentifier(this.variableName); if (localVariable != null) { // Found a variable defined in the method's header return(localVariable); } if (this.type == IdentifierType.UnQualifiedName) { // 1). we check if the variable exists in the function's scope // 2). check if the variable exits in the current context (error if not found) // // if(((IDictionary<String, Object>)($FunctionScope).ContainsKey($VARIABLE)) // { // return $FunctionScope.$VARIABLE; // } // else // { // return $GlobalScope.$VARIABLE // } // DLR.Expression getVariable = DLR.Expression.Condition( DLR.Expression.Call( DLR.Expression.Convert(variableContainer, typeof(IDictionary <string, object>)), typeof(IDictionary <string, object>).GetMethod("ContainsKey"), DLR.Expression.Constant(this.variableName) ), // True case: DLR.Expression.Dynamic( runtime.GetMemberBinder(this.variableName), typeof(object), variableContainer ), // False case: BuildGlobalAccessor(scope, runtime, parentVariableContainer, contextParts), // resulting type typeof(object) ); result = DLR.Expression.Dynamic( runtime.ConvertBinder(typeof(AType)), typeof(AType), getVariable ); return(result); } else if (this.type == IdentifierType.QualifiedName) { // Found a variable like: .var // for this check the parent's variables variableContainer = parentVariableContainer; // Fallback to the non-method case } } result = Tools.CloneMemoryMappedFile(BuildGlobalAccessor(scope, runtime, variableContainer, contextParts)); return(result); }
internal static DLR.Expression BuildCallbackCall(AplusScope scope, DLR.ParameterExpression valueParam) { // callback /* * CallbackItem callback; * if(CallbackManager.TryGetCallback(globalName, out callback) * { * CallbackBinder.Invoke(...); * } */ DLR.ParameterExpression callbackParameter = DLR.Expression.Parameter(typeof(CallbackItem), "__CALLBACK__"); DLR.Expression callback = DLR.Expression.Block( new DLR.ParameterExpression[] { callbackParameter }, DLR.Expression.IfThen( DLR.Expression.Call( scope.GetRuntimeExpression().Property("CallbackManager"), typeof(CallbackManager).GetMethod("TryGetCallback"), scope.CallbackInfo.QualifiedName, callbackParameter ), DLR.Expression.Dynamic( // TODO: do not instantiate the binder here new Runtime.Binder.CallbackBinder(), typeof(object), callbackParameter, scope.GetRuntimeExpression(), valueParam, scope.CallbackInfo.Index, scope.CallbackInfo.Path ) ) ); return callback; }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; // Target condition DLR.Expression target = this.expression.Generate(scope); DLR.Expression defaultNode = this.defaultCase.Generate(scope); if (this.caseList.Length > 0) { List<DLR.SwitchCase> cases = new List<DLR.SwitchCase>(); for (int i = 0; i < this.caseList.Length; i += 2) { // Add each case // 1. (i+1) is the case's codeblock // 2. (i) is the case's test value cases.Add( DLR.Expression.SwitchCase( this.caseList[i + 1].Generate(scope), this.caseList[i].Generate(scope) ) ); } result = DLR.Expression.Switch( typeof(AType), target, defaultNode, comparisonMethod, cases ); } else { result = DLR.Expression.Block(target, defaultNode); } return result; }
/// <summary> /// Build DLR expression for: (,target)[indexExpression] /// </summary> /// <param name="scope"></param> /// <param name="target"></param> /// <param name="indexExpression">The indexer expression containing the expression returned from <see cref="BuildIndicesList"/></param> /// <returns></returns> internal static DLR.Expression BuildIndexing(AplusScope scope, DLR.Expression target, DLR.Expression indexExpression) { var execute = typeof(AbstractMonadicFunction).GetMethod("Execute"); DLR.ParameterExpression indexes = DLR.Expression.Parameter(typeof(List<AType>), "_INDEX_"); // (,x) DLR.Expression raveledRight = DLR.Expression.Call( DLR.Expression.Constant(MonadicFunctionInstance.Ravel), execute, target, scope.GetRuntimeExpression() ); // (,x)[indexExpression] := .. DLR.Expression result = DLR.Expression.Convert( DLR.Expression.Block( new DLR.ParameterExpression[] { indexes }, DLR.Expression.Assign( indexes, DLR.Expression.Call( typeof(Helpers).GetMethod("BuildIndexerArray"), DLR.Expression.NewArrayInit(typeof(AType), indexExpression) ) ), DLR.Expression.Assign( scope.CallbackInfo.Index, DLR.Expression.Call( typeof(Tools).GetMethod("ConvertATypeListToAType", BindingFlags.NonPublic | BindingFlags.Static), indexes ) ), DLR.Expression.Dynamic( scope.GetRuntime().GetIndexBinder(new DYN.CallInfo(1)), typeof(object), raveledRight, indexes ) ), typeof(AType) ); return result; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); // Default result LinkedList <DLR.Expression> codeBlock = new LinkedList <DLR.Expression>(); codeBlock.AddLast(DLR.Expression.Constant(Utils.ANull())); switch (this.command) { case "$off": Environment.Exit(0); break; case "$laod": // Compatibility with original A+ interpreter case "$load": IDictionary <string, AType> items = runtime.ContextLoader.FindContextElements(this.argument); if (items.Count > 0) { foreach (KeyValuePair <string, AType> item in items) { codeBlock.AddFirst( VariableHelper.SetVariable( runtime, scope.GetModuleExpression(), new string[] { this.argument, item.Key }, DLR.Expression.Constant(item.Value) ) ); } } else { string path = Util.GetPath(runtime, ASymbol.Create(this.argument), ".a+"); if (File.Exists(path)) { // TODO: Save working directory and restore. // Save the previous context. string previousContext = runtime.CurrentContext; // Create the AST from file // TODO: fix the third function info argument Node fileAST = Parse.LoadFile(path, runtime.LexerMode, null); // And generate the DLR tree codeBlock.AddFirst(fileAST.Generate(scope)); // Restore the previous context runtime.CurrentContext = previousContext; } else { codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Constant(Helpers.BuildString(String.Format("Invalid file: {0}", this.argument))) ); } } break; case "$mode": if (this.argument != null) { codeBlock.AddFirst( DLR.Expression.Call( scope.RuntimeExpression, typeof(Aplus).GetMethod("SwitchLexerMode"), DLR.Expression.Constant(this.argument) ) ); } else { codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(Runtime.Helpers.BuildString(runtime.LexerMode.ToString()))); } break; case "$cx": if (this.argument != null) { runtime.CurrentContext = this.argument; } else { codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildString"), DLR.Expression.Property(scope.RuntimeExpression, "CurrentContext") ) ); } break; case "$cxs": codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Call( typeof(Runtime.SystemCommands).GetMethod("PrintContexts"), scope.GetModuleExpression() ) ); break; case "$pp": int precision = -1; if (this.argument != null && int.TryParse(this.argument, out precision) && precision >= 0) { runtime.SystemVariables["pp"] = AInteger.Create(precision); } else { codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(runtime.SystemVariables["pp"])); } break; case "$stop": if (this.argument != null) { int stopNumber; if (!int.TryParse(this.argument, out stopNumber) || stopNumber > 2 || stopNumber < 0) { stopNumber = 0; } runtime.SystemVariables["stop"] = AInteger.Create(stopNumber); } else { string resultText; switch (runtime.SystemVariables["stop"].asInteger) { default: case 0: resultText = "0 off"; break; case 1: resultText = "1 on [warning]"; break; case 2: resultText = "2 trace"; break; } codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(Helpers.BuildString(resultText))); } break; default: if (this.command.StartsWith("$>")) { string variable = this.command.Substring(2); if (this.argument == null || this.argument.Length == 0 || variable.Length == 0) { Console.WriteLine("incorrect"); } else { codeBlock.AddFirst( DLR.Expression.Call( typeof(SystemCommands).GetMethod("WriteToFile"), DLR.Expression.Constant(runtime), DLR.Expression.Constant(variable), DLR.Expression.Constant(this.argument) ) ); } } else { Console.WriteLine("Unknown system command: {0} {1}", this.command, this.argument); } break; } DLR.Expression result = DLR.Expression.Block(codeBlock); return(result); }
private static DLR.Expression GenerateIndexAssign(AplusScope scope, Indexing target, DLR.Expression value) { DLR.Expression result; if (target.IndexExpression == null) { result = DLR.Expression.Dynamic( scope.GetRuntime().SetIndexBinder(new DYN.CallInfo(0)), typeof(object), target.Item.Generate(scope), DLR.Expression.Constant(null), value ); } else { IEnumerable<DLR.Expression> indexerValues = target.IndexExpression.Items.Reverse().Select( item => { return item.Generate(scope); } ); DLR.ParameterExpression indexerParam = DLR.Expression.Parameter(typeof(List<AType>), "__INDEX__"); DLR.Expression call = DLR.Expression.Call( typeof(Helpers).GetMethod("BuildIndexerArray"), DLR.Expression.NewArrayInit(typeof(AType), indexerValues) ); Aplus runtime = scope.GetRuntime(); string qualifiedName = ((Identifier)target.Item).BuildQualifiedName(runtime.CurrentContext); DLR.ParameterExpression temp = DLR.Expression.Parameter(typeof(AType)); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); DLR.Expression callback = BuildCallbackCall(scope, temp); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, temp); result = DLR.Expression.Block( new DLR.ParameterExpression[] { indexerParam, temp }, DLR.Expression.Assign( indexerParam, call ), DLR.Expression.Assign( scope.CallbackInfo.Index, DLR.Expression.Call( typeof(Tools).GetMethod("ConvertATypeListToAType", BindingFlags.NonPublic | BindingFlags.Static), indexerParam ) ), DLR.Expression.Assign( scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName) ), DLR.Expression.Assign(temp, value), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Dynamic( scope.GetRuntime().SetIndexBinder(new System.Dynamic.CallInfo(target.IndexExpression.Length)), typeof(object), target.Item.Generate(scope), indexerParam, value ), DLR.Expression.Assign(temp, value), callback ) ), scope.CallbackInfo.NonPresetValue ); } return DLR.Expression.Convert(result, typeof(AType)); }
private DLR.Expression GenerateDyadic(AplusScope scope, DLR.Expression right, DLR.Expression left) { DLR.Expression result; DLR.ParameterExpression environment = scope.GetRuntimeExpression(); if (this.token.Type == Tokens.OR) { DLR.ParameterExpression leftParam = DLR.Expression.Variable(typeof(AType), "$$leftParam"); DLR.ParameterExpression rightParam = DLR.Expression.Variable(typeof(AType), "$$rightParam"); DLR.ParameterExpression valueParam = DLR.Expression.Variable(typeof(AType), "$$valueParam"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { leftParam, rightParam, valueParam }, DLR.Expression.Assign(rightParam, right), DLR.Expression.Assign(leftParam, left), DLR.Expression.IfThenElse( // $left.IsNumber || ($left.Type == ATypes.ANull) DLR.Expression.OrElse( DLR.Expression.IsTrue( DLR.Expression.PropertyOrField(leftParam, "IsNumber") ), DLR.Expression.Equal( DLR.Expression.PropertyOrField(leftParam, "Type"), DLR.Expression.Constant(ATypes.ANull) ) ), // Or($right, $left) DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Or), DyadicFunctionInstance.Or.GetType().GetMethod("Execute"), rightParam, leftParam, environment ) ), // Cast($right, $left) DLR.Expression.Assign( valueParam, DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Cast), DyadicFunctionInstance.Cast.GetType().GetMethod("Execute"), rightParam, leftParam, environment ) ) ), valueParam ); } else if (this.token.Type == Tokens.BWOR) { DLR.ParameterExpression rightParam = DLR.Expression.Variable(typeof(AType), "$$rightParam"); DLR.ParameterExpression leftParam = DLR.Expression.Variable(typeof(AType), "$$leftParam"); result = DLR.Expression.Block( new DLR.ParameterExpression[] { leftParam, rightParam }, DLR.Expression.Assign(rightParam, right), DLR.Expression.Assign(leftParam, left), DLR.Expression.Condition( // $left.Type == ATypes.ASymbol DLR.Expression.Equal( leftParam.Property("Type"), DLR.Expression.Constant(ATypes.ASymbol) ), DLR.Expression.Constant(DyadicFunctionInstance.BitwiseCast).Call <BitwiseCast>( "Execute", rightParam, leftParam, environment ), DLR.Expression.Constant(DyadicFunctionInstance.BitwiseOr).Call <BitwiseOr>( "Execute", rightParam, leftParam, environment ) ) ); } else { AbstractDyadicFunction method = MethodChooser.GetDyadicMethod(this.token); if (method == null) { throw new ParseException(String.Format("Not supported Dyadic function[{0}]", this.token)); } result = DLR.Expression.Call( DLR.Expression.Constant(method), method.GetType().GetMethod("Execute"), right, left, environment ); } return(result); }
public override DLR.Expression Generate(AplusScope scope) { DLR.ParameterExpression value = DLR.Expression.Parameter(typeof(AType), "__VALUE__"); DLR.ParameterExpression targetParameter = DLR.Expression.Parameter(typeof(AType), "__TARGET__"); DLR.ParameterExpression assignDone = DLR.Expression.Parameter(typeof(bool), "__ASSIGNDONE__"); DLR.ParameterExpression prevAssignDone = scope.AssignDone; scope.AssignDone = assignDone; CallbackInfoStorage savedCallbackInfos = scope.CallbackInfo; CallbackInfoStorage callbackInfos = new CallbackInfoStorage() { Index = DLR.Expression.Parameter(typeof(AType), "__CALLBACKINDEX__"), QualifiedName = DLR.Expression.Parameter(typeof(string), "__QUALIFIEDNAME__"), Path = DLR.Expression.Parameter(typeof(AType), "__PATH__"), NonPresetValue = DLR.Expression.Parameter(typeof(AType), "__NONPRESETVALUE__") }; scope.CallbackInfo = callbackInfos; // Clone the rhs value of the assignment to ensure correct results // in case of: a:=b:=[...:=] [rhs] assignments DLR.ParameterExpression environment = scope.GetRuntimeExpression(); DLR.Expression result = null; if (this.target is Identifier) { result = GenerateIdentifierAssign(scope, (AST.Identifier)this.target, value); } else if (this.target is Strand) { result = GenerateStrandAssign(scope, (Strand)this.target, value); } else if (this.target is Indexing) { Indexing target = (Indexing)this.target; // in case of: a[,] := ... if (target.IndexExpression != null && target.IndexExpression[0] is BuiltInFunction) { BuiltInFunction function = (BuiltInFunction)target.IndexExpression[0]; if (function.Function.Type != Grammar.Tokens.RAVEL) { // incorrect function inside the index expression throw new ParseException("Incorrect function", false); } var flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static; scope.IsAssignment = true; DLR.Expression item = target.Item.Generate(scope); scope.IsAssignment = false; DLR.ParameterExpression param = DLR.Expression.Parameter(typeof(AType)); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); DLR.Expression callback = BuildCallbackCall(scope, value); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, value); result = DLR.Expression.Block( new DLR.ParameterExpression[] { param }, DLR.Expression.Assign(param, item), DLR.Expression.Call( typeof(Assign).GetMethod("CalculateIndexes", flags), value, param, environment, scope.CallbackInfo.Index ), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Call( typeof(Assign).GetMethod("AppendItem", flags), value, param, environment ), callback ) ), scope.CallbackInfo.NonPresetValue ); } else { result = GenerateIndexAssign(scope, target, value); } } else if (Node.TestMonadicToken(this.target, Grammar.Tokens.VALUE)) { var method = typeof(Value).GetMethod("Assign"); var targetDLR = ((MonadicFunction)this.target).Expression.Generate(scope); DLR.Expression callback = BuildCallbackCall(scope, value); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, value); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); DLR.ParameterExpression target = DLR.Expression.Parameter(typeof(AType), "__VALUETARGET__"); MethodInfo genericMethod = typeof(Value).GetMethod("CheckArgument", BindingFlags.Static | BindingFlags.NonPublic); DLR.Expression nameMaker = DLR.Expression.Block( DLR.Expression.Call( genericMethod.MakeGenericMethod(typeof(Value)), target ), DLR.Expression.Call( VariableHelper.BuildValueQualifiedNameMethod, scope.RuntimeExpression.Property("CurrentContext"), target.Property("asString") ) ); result = DLR.Expression.Block( new DLR.ParameterExpression[] { target }, DLR.Expression.Assign(target, targetDLR), DLR.Expression.Assign( scope.CallbackInfo.QualifiedName, nameMaker ), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Call( method, target, value, environment ), callback ) ), scope.CallbackInfo.NonPresetValue ); } else if (Node.TestDyadicToken(this.target, Grammar.Tokens.VALUEINCONTEXT)) { var targetNode = (DyadicFunction)this.target; var method = typeof(ValueInContext).GetMethod("Assign"); var targetDLR = targetNode.Right.Generate(scope); var contextNameDLR = targetNode.Left.Generate(scope); DLR.Expression callback = BuildCallbackCall(scope, value); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, value); DLR.ParameterExpression target = DLR.Expression.Parameter(typeof(AType), "__VALUETARGET__"); DLR.ParameterExpression contextName = DLR.Expression.Parameter(typeof(AType), "__CONTEXTNAME__"); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); MethodInfo genericMethod = typeof(Value).GetMethod("CheckArgument", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo chosenMethod = genericMethod.MakeGenericMethod(typeof(ValueInContext)); DLR.Expression nameMaker = DLR.Expression.Block( DLR.Expression.Call(chosenMethod, contextName), DLR.Expression.Call(chosenMethod, target), DLR.Expression.Call( VariableHelper.BuildValueQualifiedNameMethod, contextName.Property("asString"), target.Property("asString") ) ); result = DLR.Expression.Block( new DLR.ParameterExpression[] { target, contextName }, DLR.Expression.Assign(target, targetDLR), DLR.Expression.Assign(contextName, contextNameDLR), DLR.Expression.Assign( scope.CallbackInfo.QualifiedName, nameMaker ), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Call( method, target, contextName, value, environment ), callback ) ), scope.CallbackInfo.NonPresetValue ); } else if (Node.TestDyadicToken(this.target, Grammar.Tokens.PICK)) { result = BuildPickAssign(scope, value); } else { var flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static; // switch on Assignment flag scope.IsAssignment = true; // Find the correct method for assignment // for pick we need a different method currently.. var method = typeof(Assign).GetMethod("AssignHelper", flags); DLR.Expression callback = AST.Assign.BuildCallbackCall(scope, value); DLR.Expression presetCallback = BuildPresetCallbackCall(scope, value); DLR.ParameterExpression temp = DLR.Expression.Parameter(typeof(AType)); DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal)); result = DLR.Expression.Block( new DLR.ParameterExpression[] { temp }, DLR.Expression.Assign(temp, this.target.Generate(scope)), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(value, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( DLR.Expression.Call( method, value, temp ), callback ) ) ); // switch off Assignment flag scope.IsAssignment = false; } // error parameter DLR.ParameterExpression errorVariable = DLR.Expression.Parameter(typeof(Error.Signal), "error"); /** * The dark magic behind callbacks: * $value := the value of the right side of assignment * $target := the left side of the assignment * $qualifiedName := the name of the assigned variable * $index := the index of the assigned variable (if any) * $path := the path of the assigned variable (if any) * * example for preset callback assignment * a := x := y * if we have a preset callback on x, then the x will get the value of the preset callback on x, * a will be y (or the value of the preset callback on a) * in any case we will result y */ DLR.Expression blockedResult = DLR.Expression.Block( new DLR.ParameterExpression[] { value, scope.AssignDone, scope.CallbackInfo.QualifiedName, scope.CallbackInfo.Index, scope.CallbackInfo.Path,scope.CallbackInfo.NonPresetValue }, DLR.Expression.Assign(scope.CallbackInfo.QualifiedName, DLR.Expression.Constant("")), DLR.Expression.Assign(scope.CallbackInfo.Index, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Assign(scope.CallbackInfo.Path, DLR.Expression.Constant(Utils.ANull())), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true, typeof(bool))), DLR.Expression.Assign(scope.CallbackInfo.NonPresetValue, DLR.Expression.Constant(null, typeof(AType))), DLR.Expression.Assign(value, this.expression.Generate(scope)), DLR.Expression.IfThen( DLR.Expression.Equal(scope.CallbackInfo.NonPresetValue, DLR.Expression.Constant(null, typeof(AType))), DLR.Expression.Assign(scope.CallbackInfo.NonPresetValue, value) ), DLR.Expression.Assign( value, DLR.Expression.Condition( DLR.Expression.Property(value, "IsMemoryMappedFile"), value, DLR.Expression.Call( value, typeof(AType).GetMethod("Clone") ) ) ), result, scope.CallbackInfo.NonPresetValue ); scope.CallbackInfo = savedCallbackInfos; scope.AssignDone = prevAssignDone; return blockedResult; }
public override DLR.Expression Generate(AplusScope scope) { DLR.Expression result; if (scope.IsAssignment && TokenUtils.AllowedPrimitiveFunction(this.token.Type)) { /* * input: y -> left side, x -> right side, value * Perform the function like this: * * i := f{y; iota rho x} * (,x)[i] := value * * where 'f' is the dyadic function */ DLR.Expression left = this.leftExpression.Generate(scope); DLR.Expression right = Node.TestMonadicToken(this.rightExpression, Tokens.RAVEL) ? ((MonadicFunction)this.rightExpression).Expression.Generate(scope) : this.rightExpression.Generate(scope) ; // i:=(iota rho x) DLR.Expression indices = AST.Assign.BuildIndicesList(scope, right); // (,x)[f{a;i}] result = AST.Assign.BuildIndexing(scope, right, GenerateDyadic(scope, indices, left)); } else if (scope.IsAssignment && this.token.Type == Tokens.CHOOSE) { scope.IsAssignment = false; DLR.Expression left = this.leftExpression.Generate(scope); scope.IsAssignment = true; DLR.Expression right = this.rightExpression.Generate(scope); result = DLR.Expression.Block( DLR.Expression.Assign(scope.CallbackInfo.Index, left), DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Choose), DyadicFunctionInstance.Choose.GetType().GetMethod("Assign"), right, left, scope.GetRuntimeExpression() ) ); } else if (scope.IsAssignment && this.token.Type == Tokens.PICK) { scope.IsAssignment = false; DLR.Expression left = this.leftExpression.Generate(scope); scope.IsAssignment = true; DLR.Expression right = this.rightExpression.Generate(scope); result = DLR.Expression.Block( DLR.Expression.Assign(scope.CallbackInfo.Path, left), DLR.Expression.Call( DLR.Expression.Constant(DyadicFunctionInstance.Pick), DyadicFunctionInstance.Pick.GetType().GetMethod("Execute"), right, left, scope.GetRuntimeExpression() ) ); } else { DLR.Expression left = this.leftExpression.Generate(scope); DLR.Expression right = this.rightExpression.Generate(scope); result = GenerateDyadic(scope, right, left); } return(result); }
private static DLR.Expression BuildGlobalAssignment( AplusScope scope, Aplus runtime, DLR.Expression variableContainer, Identifier target, DLR.Expression value, bool isStrand = false, bool needCallback = true ) { // Build the ET for updating the dependency DLR.Expression dependencyCall; string qualifiedName = target.BuildQualifiedName(runtime.CurrentContext); if (isStrand) { // We are inside a starnd assignment, do nothing. // Dependency update will be handled later. dependencyCall = DLR.Expression.Empty(); } else { // Otherwise build the dependency invalidation call. DLR.Expression dependencyManager = DLR.Expression.Property(scope.GetRuntimeExpression(), "DependencyManager"); dependencyCall = DLR.Expression.Call( dependencyManager, typeof(DependencyManager).GetMethod("InvalidateDependencies", new Type[] { typeof(string) }), DLR.Expression.Constant(qualifiedName) ); } DLR.ParameterExpression errorParam = DLR.Expression.Parameter(typeof(Error.Signal), "__ERRORPARAM__"); DLR.ParameterExpression valueParam = DLR.Expression.Parameter(typeof(AType), "__VALUEPARAMETER__"); scope.AssignDone = (scope.AssignDone == null) ? DLR.Expression.Parameter(typeof(bool), "__ASSIGNDONE__") : scope.AssignDone; DLR.Expression presetCallback = BuildPresetCallbackCall(scope, valueParam); DLR.Expression callback = BuildCallbackCall(scope, valueParam); DLR.Expression variableSet = DLR.Expression.Block( VariableHelper.SetVariable( runtime, variableContainer, target.CreateContextNames(runtime.CurrentContext), valueParam ), dependencyCall ); DLR.Expression codebody; if (needCallback) { codebody = DLR.Expression.Block( typeof(void), DLR.Expression.Assign(scope.CallbackInfo.QualifiedName, DLR.Expression.Constant(qualifiedName)), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(false)), DLR.Expression.TryCatch( DLR.Expression.Block( typeof(void), DLR.Expression.Assign(valueParam, presetCallback), DLR.Expression.Assign(scope.AssignDone, DLR.Expression.Constant(true)) ), DLR.Expression.Catch( errorParam, DLR.Expression.Empty() ) ), DLR.Expression.IfThen( scope.AssignDone, DLR.Expression.Block( variableSet, callback ) ) ); } else { codebody = variableSet; } // value assignment DLR.Expression result = DLR.Expression.Block( new DLR.ParameterExpression[] { valueParam }, DLR.Expression.Assign(valueParam, value), codebody, valueParam ); return result; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); if (scope.IsEval && scope.IsMethod) { // we are inside a function and an eval block. // override the original eval scope // create a top level scope scope = new AplusScope(null, "_EVAL_FUNC_SCOPE_", scope.GetRuntime(), scope.GetRuntimeExpression(), scope.Parent.GetModuleExpression(), scope.ReturnTarget, isEval: true ); } string operatorName = this.name.BuildQualifiedName(runtime.CurrentContext); string scopename = String.Format("__operator_{0}_scope__", this.name.Name); AplusScope methodScope = new AplusScope(scope, scopename, runtimeParam: DLR.Expression.Parameter(typeof(Aplus), "_EXTERNAL_RUNTIME_"), moduleParam: DLR.Expression.Parameter(typeof(DYN.ExpandoObject), scopename), returnTarget: DLR.Expression.Label(typeof(AType), "RETURN"), isMethod: true ); // create a result parameter DLR.ParameterExpression resultParameter = DLR.Expression.Parameter(typeof(AType), "__RESULT__"); // create function's parameters LinkedList<DLR.ParameterExpression> methodParameters = new LinkedList<DLR.ParameterExpression>(); // add parameters to the linkedlist BuildParameterExpression(methodScope, methodParameters, leftArgument); BuildParameterExpression(methodScope, methodParameters, function); BuildParameterExpression(methodScope, methodParameters, condition); BuildParameterExpression(methodScope, methodParameters, rightArgument); // add parameter for AplusEnviroment methodParameters.AddFirst(methodScope.RuntimeExpression); // create the lambda method for the function DLR.LambdaExpression method = DLR.Expression.Lambda( DLR.Expression.Block( new DLR.ParameterExpression[] { methodScope.ModuleExpression, resultParameter }, // add the local scope's store DLR.Expression.Assign(methodScope.ModuleExpression, DLR.Expression.Constant(new DYN.ExpandoObject())), // set AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), methodScope.ModuleExpression ), // calculate the result of the defined function DLR.Expression.Assign( resultParameter, DLR.Expression.Label(methodScope.ReturnTarget, this.codeblock.Generate(methodScope)) ), // reset AplusEnviroment's function scope reference DLR.Expression.Assign( DLR.Expression.Property(methodScope.RuntimeExpression, "FunctionScope"), DLR.Expression.Constant(null, typeof(DYN.ExpandoObject)) ), // return the result resultParameter ), operatorName, methodParameters ); // wrap the lambda method inside an AFunc DLR.Expression wrappedLambda = DLR.Expression.Call( typeof(AFunc).GetMethod("CreateUserOperator"), DLR.Expression.Constant(operatorName), DLR.Expression.Constant(this.IsDyadicOperator), method, DLR.Expression.Constant(methodParameters.Count), DLR.Expression.Constant(this.codeText) ); // set the variable to the lambda function DLR.Expression setMethod = VariableHelper.SetVariable( runtime, scope.ModuleExpression, this.name.CreateContextNames(runtime.CurrentContext), wrappedLambda ); // ensure the result type to be an AType DLR.Expression result = DLR.Expression.Convert(setMethod, typeof(AType)); return result; }
private static DLR.Expression BuildMonadicCase( AplusScope scope, Operator op, DLR.ParameterExpression functionVariable, DLR.LabelTarget methodReturnTarget, DLR.ParameterExpression methodEnvArg, DLR.ParameterExpression methodRightArg) { DLR.Expression result; if (op is EachOperator) { result = DLR.Expression.IfThenElse( DLR.Expression.Property(functionVariable, "IsFunctionScalar"), DLR.Expression.Goto( methodReturnTarget, DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Apply), MonadicOperatorInstance.Apply.GetType().GetMethod("Execute"), functionVariable, methodRightArg, methodEnvArg ) ), DLR.Expression.Goto( methodReturnTarget, DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Each), MonadicOperatorInstance.Each.GetType().GetMethod("Execute"), functionVariable, methodRightArg, methodEnvArg ) ) ); } else { result = DLR.Expression.Goto( methodReturnTarget, DLR.Expression.Call( DLR.Expression.Constant(MonadicOperatorInstance.Rank), MonadicOperatorInstance.Rank.GetType().GetMethod("Execute"), functionVariable, ((RankOperator)op).Condition.Generate(scope), methodRightArg, methodEnvArg ) ); } return result; }
/// <summary> /// Adds the passed parameter's name to the scope, and the parameterexpression to the expression linkedlist. /// </summary> /// <param name="methodScope">The scope.</param> /// <param name="methodParameters">The LinkedList to add.</param> /// <param name="parameter">The parameter to add.</param> private static void BuildParameterExpression( AplusScope methodScope, LinkedList<DLR.ParameterExpression> methodParameters, Identifier parameter) { if (parameter != null) { string name = parameter.Name; DLR.ParameterExpression expression = DLR.Expression.Parameter(typeof(AType), name); methodScope.Variables[name] = expression; methodParameters.AddFirst(expression); } }
public override DLR.Expression Generate(AplusScope scope) { // TODO: Add usage of Protected Execute Flag // Save the previous return target DLR.LabelTarget oldTarget = scope.ReturnTarget; scope.ReturnTarget = DLR.Expression.Label(typeof(AType), "EXIT"); DLR.Expression protectedCode = DLR.Expression.Label( scope.ReturnTarget, this.codeblock.Generate(scope) ); // Restore the return target; scope.ReturnTarget = oldTarget; // Code block contining the strandard execution's result // wrapped in a strand DLR.Expression block = DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), // We need to pass in reverse order protectedCode, DLR.Expression.Constant(AInteger.Create(0), typeof(AType)) ) ); // Parameter for Catch block DLR.ParameterExpression errorVariable = DLR.Expression.Parameter(typeof(Error), "error"); // Catch block, returns the ([errorcode]; [errortext]) strand DLR.CatchBlock catchBlock = DLR.Expression.Catch( errorVariable, DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildStrand"), DLR.Expression.NewArrayInit( typeof(AType), // We need to pass in reverse order // Error Text DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildString"), DLR.Expression.Property(errorVariable, "ErrorText") ), // Error Code DLR.Expression.Call( typeof(AInteger).GetMethod("Create", new Type[] { typeof(int) }), DLR.Expression.Convert( DLR.Expression.Property(errorVariable, "ErrorType"), typeof(int) ) ) ) ) ); DLR.Expression result = DLR.Expression.TryCatch( block, catchBlock ); return result; }
public override DLR.Expression Generate(AplusScope scope) { Aplus runtime = scope.GetRuntime(); // Default result LinkedList<DLR.Expression> codeBlock = new LinkedList<DLR.Expression>(); codeBlock.AddLast(DLR.Expression.Constant(Utils.ANull())); switch (this.command) { case "$off": Environment.Exit(0); break; case "$laod": // Compatibility with original A+ interpreter case "$load": IDictionary<string, AType> items = runtime.ContextLoader.FindContextElements(this.argument); if (items.Count > 0) { foreach (KeyValuePair<string, AType> item in items) { codeBlock.AddFirst( VariableHelper.SetVariable( runtime, scope.GetModuleExpression(), new string[] { this.argument, item.Key }, DLR.Expression.Constant(item.Value) ) ); } } else { string path = Util.GetPath(runtime, ASymbol.Create(this.argument), ".a+"); if (File.Exists(path)) { // TODO: Save working directory and restore. // Save the previous context. string previousContext = runtime.CurrentContext; // Create the AST from file // TODO: fix the third function info argument Node fileAST = Parse.LoadFile(path, runtime.LexerMode, null); // And generate the DLR tree codeBlock.AddFirst(fileAST.Generate(scope)); // Restore the previous context runtime.CurrentContext = previousContext; } else { codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Constant(Helpers.BuildString(String.Format("Invalid file: {0}", this.argument))) ); } } break; case "$mode": if (this.argument != null) { codeBlock.AddFirst( DLR.Expression.Call( scope.RuntimeExpression, typeof(Aplus).GetMethod("SwitchLexerMode"), DLR.Expression.Constant(this.argument) ) ); } else { codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(Runtime.Helpers.BuildString(runtime.LexerMode.ToString()))); } break; case "$cx": if (this.argument != null) { runtime.CurrentContext = this.argument; } else { codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Call( typeof(Runtime.Helpers).GetMethod("BuildString"), DLR.Expression.Property(scope.RuntimeExpression, "CurrentContext") ) ); } break; case "$cxs": codeBlock.Clear(); codeBlock.AddFirst( DLR.Expression.Call( typeof(Runtime.SystemCommands).GetMethod("PrintContexts"), scope.GetModuleExpression() ) ); break; case "$pp": int precision = -1; if (this.argument != null && int.TryParse(this.argument, out precision) && precision >= 0) { runtime.SystemVariables["pp"] = AInteger.Create(precision); } else { codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(runtime.SystemVariables["pp"])); } break; case "$stop": if (this.argument != null) { int stopNumber; if (!int.TryParse(this.argument, out stopNumber) || stopNumber > 2 || stopNumber < 0) { stopNumber = 0; } runtime.SystemVariables["stop"] = AInteger.Create(stopNumber); } else { string resultText; switch (runtime.SystemVariables["stop"].asInteger) { default: case 0: resultText = "0 off"; break; case 1: resultText = "1 on [warning]"; break; case 2: resultText = "2 trace"; break; } codeBlock.Clear(); codeBlock.AddFirst(DLR.Expression.Constant(Helpers.BuildString(resultText))); } break; default: if (this.command.StartsWith("$>")) { string variable = this.command.Substring(2); if (this.argument == null || this.argument.Length == 0 || variable.Length == 0) { Console.WriteLine("incorrect"); } else { codeBlock.AddFirst( DLR.Expression.Call( typeof(SystemCommands).GetMethod("WriteToFile"), DLR.Expression.Constant(runtime), DLR.Expression.Constant(variable), DLR.Expression.Constant(this.argument) ) ); } } else { Console.WriteLine("Unknown system command: {0} {1}", this.command, this.argument); } break; } DLR.Expression result = DLR.Expression.Block(codeBlock); return result; }