//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="ExpRepeatNode.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the “Software”), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and // this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED “AS IS”, // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //----------------------------------------------------------------------- //----------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Threading.Channels; namespace StgSharp.Script.Express { public class ExpRepeatNode : ExpSyntaxNode { private ExpElementInstance _variable; private ExpSyntaxNode _begin, _end, _increment, _operationBegin,_untilRule,_whileRule; internal ExpRepeatNode( Token source, ExpElementInstance variable, ExpSyntaxNode begin, ExpSyntaxNode end, ExpSyntaxNode increment, ExpSyntaxNode operationBegin, ExpSyntaxNode untilRule, ExpSyntaxNode whileRule ) : base( source ) { if( variable.NodeFlag != begin.NodeFlag || begin.NodeFlag != end.NodeFlag || ( increment != null && end.NodeFlag != increment.NodeFlag ) ) { throw new InvalidCastException(); } if( IsNullOrEmpty( increment ) ) { switch( ( ExpNodeFlag )variable.NodeFlag | ExpNodeFlag.BuiltinType_Any ) { case ExpNodeFlag.BuiltinType_Real: increment = new ExpRealNumberNode( new Token( ExpressCompile.PoolString( "1.0f" ), source.Line, -1, TokenFlag.Number ), 1.0f, isLiteral: true ); break; case ExpNodeFlag.BuiltinType_Int: increment = new ExpIntNode( new Token( ExpressCompile.PoolString( "1" ), source.Line, -1, TokenFlag.Number ), 1, isLiteral: true ); break; default: throw new ExpInvalidTypeException( variable, "Int or Real", "otherwise" ); } } _variable = variable; _begin = begin; _end = end; _increment = increment!; _operationBegin = operationBegin; _untilRule = untilRule; _whileRule = whileRule; } public override ExpSyntaxNode Left => throw new NotImplementedException(); public override ExpSyntaxNode Right => _operationBegin; public override IExpElementSource EqualityTypeConvert => null!; public void AppendRepeatedOperation( ExpSyntaxNode node ) { _operationBegin.AppendNode( node ); } /// /// Create an AST node for repeat expression in EXPRESS language. The loop does not has /// WHILE and UNTIL regulation. /// /// /// Position of the loop. /// /// /// The variable recording increment by step. /// /// /// Beginning value of the loop. /// /// /// When reach the value, the loop ends. /// /// /// Expressions to operate multiple times. /// /// /// A representing the repeat expression. /// public static ExpRepeatNode Create( Token t, ExpInstanceReferenceNode repeatVariable, ExpSyntaxNode begin, ExpSyntaxNode end, ExpSyntaxNode increment, ExpSyntaxNode whileRule, ExpSyntaxNode untilRule, ExpSyntaxNode body ) { untilRule = ExpBoolNode.False( null ); whileRule = ExpBoolNode.True( null ); ExpRepeatNode ret = new ExpRepeatNode( t, repeatVariable.OriginObject, begin, end, increment, body, whileRule, untilRule ) { /* * 0: variable name * 1: beginning value * 2: ending value * 3: increment * 4: body * 5: while * 6: until */ CodeConvertTemplate = $$""" for( {0} = {1}; {0} <= {2}; {0} += {3}) { if(!( {5} )) break; {4} if( {6} ) break; } """ }; return ret; } public static ExpRepeatNode Create( Token t, ExpElementInstance repeatVariable, ExpSyntaxNode begin, ExpSyntaxNode end, ExpSyntaxNode increment, ExpSyntaxNode whileRule, ExpSyntaxNode untilRule, ExpSyntaxNode body ) { whileRule = IsNullOrEmpty( whileRule ) ? ExpBoolNode.True( t ) : whileRule; untilRule = IsNullOrEmpty( untilRule ) ? ExpBoolNode.False( t ) : untilRule; ExpRepeatNode ret = new ExpRepeatNode( t, repeatVariable, begin, end, increment, body, whileRule, untilRule ) { /* * 0: variable name * 1: beginning value * 2: ending value * 3: increment * 4: body * 5: while * 6: until */ CodeConvertTemplate = $$""" for({{repeatVariable.TypeName}} {0} = {1}; {0} <= {2}; {0} += {3}) { if(!( {5} )) break; {4} if( {6} ) break; } """ }; return ret; } } }