#-----------------------------------------------------------------------------* # # @file gtl_instructions.galgas # # @section desc File description # # Instructions of GTL. # # @section copyright Copyright # # Goil OIL compiler, part of Trampoline RTOS # # Trampoline is copyright (c) CNRS, University of Nantes, # Ecole Centrale de Nantes # Trampoline is protected by the French intellectual property law. # # This software is distributed under the GNU Public Licence V2. # Check the LICENSE file in the root directory of Trampoline # # $Date$ # $Rev$ # $Author$ # $URL$ # #-----------------------------------------------------------------------------* #=============================================================================* # abstract class for a template instruction #-----------------------------------------------------------------------------* abstract class @gtlInstruction { @location where @string signature } getter @gtlInstruction location -> @location result { result = where } abstract method @gtlInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString #=============================================================================* # instruction list #-----------------------------------------------------------------------------* list @gtlInstructionList { @gtlInstruction instruction } method @gtlInstructionList execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { if [context debugActive] then [!?context pushInstructionList !self] @uint lastErrorCount = .errorCount for () in self do (index) let @bool errorCountIncreased = (@uint.errorCount - lastErrorCount) > 0 if [context breakOnNext] | [context breakOn !instruction] | [context watchOn !context !vars !lib] | errorCountIncreased then [!?context setBreakOnNext !true] [!?context setNextInstructionIndex !index] [!?context setDebugger !false] [!?context executeStepDoList !?context !?vars !?lib !?outputString] [!?context setDebugger !true] [!?context setLoopOnCommand !true] loop (@uint.max) message [context promptStyle] + "gtl> " + endc() [!?context getCommand ?let @string input] let @gtlInstruction command let @uint currentErrorCount = @uint.errorCount if [input stringByTrimmingWhiteSpaces] == "" then command = @gtlStepInstruction.new { !.here !"" } else grammar gtl_debugger_grammar on (input,"Debugger command") ?command end if @uint.errorCount == currentErrorCount then if [command mayExecuteWithoutError !context !vars !lib] then message [context outputStyle] [!?context setDebugger !false] [command execute !?context !?vars !?lib !?outputString] [!?context setDebugger !true] message endc() end end while [context loopOnCommand] do end end lastErrorCount = .errorCount [instruction execute !?context !?vars !?lib !?outputString] end [!?context popInstructionList] else for () in self do if @uint.errorCount == 0 then [instruction execute !?context !?vars !?lib !?outputString] if @uint.errorCount != 0 & [context propagateError] then error instruction : "runtime error" end end end end } #-----------------------------------------------------------------------------* # let unconstructed instruction #-----------------------------------------------------------------------------* class @gtlLetUnconstructedInstruction : @gtlInstruction { @gtlVarPath lValue } override method @gtlLetUnconstructedInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib !@gtlUnconstructed.new { ![[lValue itemAtIndex !0] location] !emptylstring() } ] } #-----------------------------------------------------------------------------* # let instructions base class #-----------------------------------------------------------------------------* abstract class @gtlAssignInstruction : @gtlLetUnconstructedInstruction { @gtlExpression rValue } #-----------------------------------------------------------------------------* # = assignment #-----------------------------------------------------------------------------* class @gtlLetInstruction : @gtlAssignInstruction {} override method @gtlLetInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![rValue eval !context !vars !lib]] } #-----------------------------------------------------------------------------* # += assignment #-----------------------------------------------------------------------------* class @gtlLetAddInstruction : @gtlAssignInstruction {} override method @gtlLetAddInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] addOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # -= assignment #-----------------------------------------------------------------------------* class @gtlLetSubstractInstruction : @gtlAssignInstruction {} override method @gtlLetSubstractInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] subOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # *= assignment #-----------------------------------------------------------------------------* class @gtlLetMultiplyInstruction : @gtlAssignInstruction {} override method @gtlLetMultiplyInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] mulOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # /= assignment #-----------------------------------------------------------------------------* class @gtlLetDivideInstruction : @gtlAssignInstruction {} override method @gtlLetDivideInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] divOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # %= assignment #-----------------------------------------------------------------------------* class @gtlLetModuloInstruction : @gtlAssignInstruction {} override method @gtlLetModuloInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] divOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # <<= assignment #-----------------------------------------------------------------------------* class @gtlLetShiftLeftInstruction : @gtlAssignInstruction {} override method @gtlLetShiftLeftInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] slOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # >>= assignment #-----------------------------------------------------------------------------* class @gtlLetShiftRightInstruction : @gtlAssignInstruction {} override method @gtlLetShiftRightInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] srOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # &= assignment #-----------------------------------------------------------------------------* class @gtlLetAndInstruction : @gtlAssignInstruction {} override method @gtlLetAndInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] andOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # |= assignment #-----------------------------------------------------------------------------* class @gtlLetOrInstruction : @gtlAssignInstruction {} override method @gtlLetOrInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] orOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # ^= assignment #-----------------------------------------------------------------------------* class @gtlLetXorInstruction : @gtlAssignInstruction {} override method @gtlLetXorInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue set !context !?vars !lib ![[lValue get !context !vars !lib] xorOp ![rValue eval !context !vars !lib]] ] } #-----------------------------------------------------------------------------* # unlet instruction #-----------------------------------------------------------------------------* class @gtlUnletInstruction : @gtlLetUnconstructedInstruction {} override method @gtlUnletInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { [lValue delete !context !?vars !lib ] } #-----------------------------------------------------------------------------* # %...% : template string instruction #-----------------------------------------------------------------------------* class @gtlTemplateStringInstruction : @gtlInstruction { @string value } override method @gtlTemplateStringInstruction execute ?!@gtlContext unused context ?!@gtlData unused vars ?!@library unused lib ?!@string outputString { outputString += value } #-----------------------------------------------------------------------------* # ! : emit instruction #-----------------------------------------------------------------------------* class @gtlEmitInstruction : @gtlInstruction { @gtlExpression rValue } override method @gtlEmitInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { outputString += [[rValue eval !context !vars !lib] string] } #-----------------------------------------------------------------------------* # write to : write the result of instruction execution to a file #-----------------------------------------------------------------------------* class @gtlWriteToInstruction : @gtlInstruction { @gtlExpression fileNameExpression @bool isExecutable @gtlInstructionList instructions } override method @gtlWriteToInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @uint currentErrorCount = @uint.errorCount let @string fullFileName = [[fileNameExpression eval !context !vars !lib] string] let @gtlString fileName = .new{ !where !emptylstring() ![fullFileName lastPathComponent] } let @gtlString filePath = .new{ !where !emptylstring() ![fullFileName nativePathWithUnixPath] } @string result = "" @gtlData varsCopy = vars # remove the current FILENAME and FILEPATH variable # and replace them with [!?varsCopy setStructFieldAtLevel !@lstring.new{!"FILENAME" !where} !fileName !0 ] [!?varsCopy setStructFieldAtLevel !@lstring.new{!"FILEPATH" !where} !filePath !0 ] if (currentErrorCount == @uint.errorCount) then [instructions execute !?context !?varsCopy !?lib !?result] if (currentErrorCount == @uint.errorCount) then if isExecutable then let @string directory = [fullFileName stringByDeletingLastPathComponent] if directory != "" then [directory makeDirectory] end [result writeToExecutableFile !fullFileName] else [result makeDirectoryAndWriteToFile !fullFileName] end end end } #-----------------------------------------------------------------------------* # template instructions : invoke a template #-----------------------------------------------------------------------------* class @gtlTemplateInstruction : @gtlInstruction { @lstring prefix @gtlExpression fileName @bool ifExists @bool isGlobal @gtlExpressionList arguments @gtlInstructionList instructionsIfNotFound } override method @gtlTemplateInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @gtlContext newContext = context if "" != prefix then [!?newContext setPrefix !prefix] end let @lstring templateFileName = [newContext fullTemplateFileName !context !vars ![[fileName eval !context !vars !lib] as @gtlString lstring] ] @gtlData localVars [!?newContext setInputVars !.emptyList] if not isGlobal then # build the variable map for the template localVars = @gtlStruct.new { !where !emptylstring() !.emptyMap } for (argumentExpression) in arguments do let @gtlData evaluedArg = [argumentExpression eval !context !vars !lib] [!?newContext addInputVariable !evaluedArg] end else localVars = vars end [!?lib getTemplate !newContext !templateFileName !ifExists !?lib ?let @bool found ?let @gtlTemplate result ] if found then [result execute !?newContext !?localVars !?lib !?outputString] else if ifExists then @gtlData localMap = [vars overrideMap] [instructionsIfNotFound execute !?context !?localMap !?lib !?outputString] vars = [localMap overriddenMap] end end [!?context setDebuggerContext ![newContext debuggerContext]] } #-----------------------------------------------------------------------------* # template instructions : set the destination variable with a number of spaces # equals to the current column number in the output string #-----------------------------------------------------------------------------* class @gtlGetColumnInstruction : @gtlInstruction { @gtlVarPath destVariable } override method @gtlGetColumnInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @string value = "" @bool searchEndOfLine = true @uint index = [outputString length] loop ([outputString length]) while (index > 0) & searchEndOfLine do searchEndOfLine = [outputString characterAtIndex !index - 1] != '\n' index-- if searchEndOfLine then value += " " end end [destVariable set !context !?vars !lib !@gtlString.new{!where !emptylstring() !value} ] } #-----------------------------------------------------------------------------* # template instructions : if statement #-----------------------------------------------------------------------------* list @gtlThenElsifStatementList { @gtlExpression condition @gtlInstructionList instructionList } class @gtlIfStatementInstruction : @gtlInstruction { @gtlThenElsifStatementList thenElsifList @gtlInstructionList elseList } override method @gtlIfStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @gtlData localMap = [vars overrideMap] @bool noConditionMatching = true for () in thenElsifList while noConditionMatching do let @gtlData dataCondition = [condition eval !context !localMap !lib] if dataCondition is == @gtlBool then let @bool boolCondition = [dataCondition as @gtlBool value] if boolCondition then [instructionList execute !?context !?localMap !?lib !?outputString] noConditionMatching = false end else error dataCondition : "bool expected" end end if noConditionMatching then [elseList execute !?context !?localMap !?lib !?outputString] end vars = [localMap overriddenMap] } #-----------------------------------------------------------------------------* # template instructions : foreach statement #-----------------------------------------------------------------------------* class @gtlForeachStatementInstruction : @gtlInstruction { @lstring keyName @lstring variableName @lstring indexName @gtlExpression iterable @gtlInstructionList beforeList @gtlInstructionList betweenList @gtlInstructionList afterList @gtlInstructionList doList } method @gtlForeachStatementInstruction iterateOnMap ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString ? let @gtlMap iterableMap { let @lstring actualKeyName = if "" == keyName then .new { !"KEY" !keyName } else keyName end for () in [iterableMap value] before [beforeList execute !?context !?vars !?lib !?outputString] do (index) [!?vars setStructField !variableName !value] [!?vars setStructField !actualKeyName !@gtlString.new { !keyName !emptylstring() ![lkey string] } ] [!?vars setStructField !indexName !@gtlInt.new { !where !emptylstring() ![index bigint] } ] [doList execute !?context !?vars !?lib !?outputString] between [betweenList execute !?context !?vars !?lib !?outputString] after [afterList execute !?context !?vars !?lib !?outputString] end } method @gtlForeachStatementInstruction iterateOnList ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString ? let @gtlList iterableList { if "" != keyName then warning keyName : "a key variable cannot be define when iterating on a list" end for () in [iterableList value] before [beforeList execute !?context !?vars !?lib !?outputString] do (index) [!?vars setStructField !variableName !value] [!?vars setStructField !indexName !@gtlInt.new { !where !emptylstring() ![index bigint] } ] [doList execute !?context !?vars !?lib !?outputString] between [betweenList execute !?context !?vars !?lib !?outputString] after [afterList execute !?context !?vars !?lib !?outputString] end } method @gtlForeachStatementInstruction iterateOnSet ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString ? let @gtlSet iterableSet { if "" != keyName then warning keyName : "a key variable cannot be define when iterating on a set" end for () in [iterableSet value] before [beforeList execute !?context !?vars !?lib !?outputString] do (index) [!?vars setStructField !variableName !@gtlString.new { !lkey !emptylstring() !lkey} ] [!?vars setStructField !indexName !@gtlInt.new { !where !emptylstring() ![index bigint] } ] [doList execute !?context !?vars !?lib !?outputString] between [betweenList execute !?context !?vars !?lib !?outputString] after [afterList execute !?context !?vars !?lib !?outputString] end } override method @gtlForeachStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @gtlData localMap = [vars overrideMap] let @gtlData iterableData = [iterable eval !context !localMap !lib] cast iterableData case == @gtlMap iterableMap: [self iterateOnMap !?context !?localMap !?lib !?outputString !iterableMap] case == @gtlList iterableList: [self iterateOnList !?context !?localMap !?lib !?outputString !iterableList] case == @gtlSet iterableSet: [self iterateOnSet !?context !?localMap !?lib !?outputString !iterableSet] else error [iterable location] : "Map, list or set expected" end vars = [localMap overriddenMap] } #-----------------------------------------------------------------------------* # template instructions : for statement #-----------------------------------------------------------------------------* class @gtlForStatementInstruction : @gtlInstruction { @lstring identifier @gtlExpressionList iterable @gtlInstructionList betweenList @gtlInstructionList doList } override method @gtlForStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { let @lstring indexName = .new{!"INDEX" !where} @gtlData localMap = [vars overrideMap] for () in iterable do (index) let @gtlData value = [expression eval !context !localMap !lib] [!?localMap setStructField !identifier !value] [!?localMap setStructField !indexName !@gtlInt.new { !where !emptylstring() ![index bigint] } ] [doList execute !?context !?localMap !?lib !?outputString] between [betweenList execute !?context !?localMap !?lib !?outputString] end vars = [localMap overriddenMap] } #-----------------------------------------------------------------------------* # template instructions : loop statement #-----------------------------------------------------------------------------* class @gtlLoopStatementInstruction : @gtlInstruction { @lstring identifier @gtlExpression start @gtlExpression stop @gtlExpression step @sint64 upDown @gtlInstructionList beforeList @gtlInstructionList betweenList @gtlInstructionList afterList @gtlInstructionList doList } override method @gtlLoopStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @gtlData localMap = [vars overrideMap] let @gtlData startData = [start eval !context !localMap !lib] let @gtlData stopData = [stop eval !context !localMap !lib] let @gtlData stepData = [step eval !context !localMap !lib] @bigint startVal let @bigint stopVal let @bigint stepVal if startData is == @gtlInt then startVal = [startData as @gtlInt value] else error [start location] : "int expected" : startVal end if stopData is == @gtlInt then stopVal = [stopData as @gtlInt value] else error [stop location] : "int expected" : stopVal end if stepData is == @gtlInt then stepVal = [stepData as @gtlInt value] * upDown else error [step location] : "int expected" : stepVal end @bigint direction = 1 if stepVal < 0 then direction = -1 end if (stopVal - startVal) * direction >= 0 then [beforeList execute !?context !?localMap !?lib !?outputString] let @uint count = [(stopVal - startVal) * direction + 1 uint] loop (count) [!?localMap setStructField !identifier !@gtlInt.new{![identifier location] !emptylstring() !startVal} ] [doList execute !?context !?localMap !?lib !?outputString] startVal = startVal + stepVal while (stopVal - startVal) * direction >= 0 do [betweenList execute !?context !?localMap !?lib !?outputString] end [afterList execute !?context !?localMap !?lib !?outputString] end vars = [localMap overriddenMap] } #-----------------------------------------------------------------------------* # template instructions : repeat statement #-----------------------------------------------------------------------------* class @gtlRepeatStatementInstruction : @gtlInstruction { @gtlExpression limit @gtlExpression condition @gtlInstructionList continueList @gtlInstructionList doList } override method @gtlRepeatStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { @gtlData localMap = [vars overrideMap] @bool boolCondition = false let @gtlData limitData = [limit eval !context !vars !lib] let @uint limitVal if limitData is == @gtlInt then limitVal = [[limitData as @gtlInt value] uint] else error limit : "int exprected" : limitVal end loop (limitVal) [continueList execute !?context !?localMap !?lib !?outputString] let @gtlData conditionData = [condition eval !context !localMap !lib] if [conditionData dynamicType] == `@gtlBool then boolCondition = [conditionData as @gtlBool value] else error conditionData : "bool expected" end while boolCondition do [doList execute !?context !?localMap !?lib !?outputString] end vars = [localMap overriddenMap] } #-----------------------------------------------------------------------------* # template instructions : error statement #-----------------------------------------------------------------------------* class @gtlErrorStatementInstruction : @gtlInstruction { @gtlVarPath identifier @bool hereInstead @gtlExpression errorMessage } override method @gtlErrorStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @location errorLocation if hereInstead then errorLocation = where else errorLocation = [[identifier get !context !vars !lib] where] end let @gtlData errorMessageData = [errorMessage eval !context !vars !lib] if [errorMessageData dynamicType] == `@gtlString then error errorLocation : [errorMessageData as @gtlString value] [!?context setPropagateError !false] else error [errorMessage location] : "string expected" end } #-----------------------------------------------------------------------------* # template instructions : warning statement #-----------------------------------------------------------------------------* class @gtlWarningStatementInstruction : @gtlInstruction { @gtlVarPath identifier @bool hereInstead @gtlExpression warningMessage } override method @gtlWarningStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @location warningLocation if hereInstead then warningLocation = where else warningLocation = [[identifier get !context !vars !lib] where] end let @gtlData warningMessageData = [warningMessage eval !context !vars !lib] if [warningMessageData dynamicType] == `@gtlString then warning warningLocation : [warningMessageData as @gtlString value] else error [warningMessage location] : "string expected" end } #-----------------------------------------------------------------------------* # template instructions : print statement #-----------------------------------------------------------------------------* class @gtlPrintStatementInstruction : @gtlInstruction { @bool carriageReturn @gtlExpression messageToPrint } override method @gtlPrintStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @string messageToPrintString = [[messageToPrint eval !context !vars !lib] string] message messageToPrintString if carriageReturn then message "\n" end } #-----------------------------------------------------------------------------* # template instructions : display statement #-----------------------------------------------------------------------------* class @gtlDisplayStatementInstruction : @gtlInstruction { @gtlVarPath variablePath } override method @gtlDisplayStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @gtlData variable = [variablePath get !context !vars !lib] message [variablePath stringPath !context !vars !lib] + " from " + [where locationString] + "\n" + [variable desc !4] } #-----------------------------------------------------------------------------* # template instructions : sort list of struct of list of scalars statement #-----------------------------------------------------------------------------* list @sortingKeyList { @lstring key @lsint order } abstract class @gtlAbstractSortInstruction : @gtlInstruction { @gtlVarPath variablePath } abstract getter @gtlAbstractSortInstruction compare ?let @gtlData s1 ?let @gtlData s2 ->@sint method @gtlAbstractSortInstruction swap ?!@list aList ?let @uint index1 ?let @uint index2 { let @gtlData temp = [aList valueAtIndex !index1] [!?aList setValueAtIndex ![aList valueAtIndex !index2] !index1] [!?aList setValueAtIndex !temp !index2] } method @gtlAbstractSortInstruction partition ?!@list aList ?let @uint min ?let @uint max ?!@uint pivotIndex { let @gtlData pivot = [aList valueAtIndex !pivotIndex] [self swap !?aList !pivotIndex !max] @uint storeIndex = min @uint i = min loop (max - min) while i < max do if [self compare ![aList valueAtIndex !i] !pivot] == -1 then [self swap !?aList !i !storeIndex] storeIndex++ end i++ end [self swap !?aList !storeIndex !max] pivotIndex = storeIndex } method @gtlAbstractSortInstruction sort ?!@list aList ?let @uint min ?let @uint max { if min < max then @uint pivotIndex = (max + min) / 2 [self partition !?aList !min !max !?pivotIndex] [self sort !?aList !min !pivotIndex] [self sort !?aList !pivotIndex+1 !max] end } override method @gtlAbstractSortInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { let @gtlData variable = [variablePath get !context !vars !lib] cast variable case == @gtlList variableList: @list listToSort = [variableList value] let @uint length = [listToSort length] if length > 0 then [self sort !?listToSort !0 !length-1] end [variablePath set !context !?vars !lib !@gtlList.new { !where !emptylstring() !listToSort } ] else [variablePath last ?let @gtlVarItem lastComponent] error lastComponent : "list expected" end } #-----------------------------------------------------------------------------* class @gtlSortStatementStructInstruction : @gtlAbstractSortInstruction { @sortingKeyList sortingKey } override getter @gtlSortStatementStructInstruction compare ?let @gtlData s1 ?let @gtlData s2 ->@sint result { result = [self compareElements !s1 !s2 !sortingKey] } getter @gtlSortStatementStructInstruction compareElements ?let @gtlData s1 ?let @gtlData s2 ?@sortingKeyList keyList ->@sint result { if [keyList length] > 0 then if s1 is == @gtlStruct then if s2 is == @gtlStruct then let @gtlStruct s1Struct = s1 as @gtlStruct let @gtlStruct s2Struct = s2 as @gtlStruct [!?keyList popFirst ?let @lstring field ?let @lsint order] [[s1Struct value] get !field ?let @gtlData s1Field] [[s2Struct value] get !field ?let @gtlData s2Field] if [s1Field ltOp !s2Field] then result = -1 * [order bigint] else if [s1Field gtOp !s2Field] then result = 1 * [order bigint] else result = [self compareElements !s1 !s2 !keyList] end end else error [s2 location] : "struct expected" : result end else error [s1 location] : "struct expected" : result end else result = 0 end } #-----------------------------------------------------------------------------* class @gtlSortStatementInstruction : @gtlAbstractSortInstruction { @lsint order } override getter @gtlSortStatementInstruction compare ?let @gtlData s1 ?let @gtlData s2 ->@sint result { if [s1 ltOp !s2] then result = -1 * [order bigint] else if [s1 gtOp !s2] then result = 1 * [order bigint] else result = 0 end end } #-----------------------------------------------------------------------------* # template instructions : tab #-----------------------------------------------------------------------------* class @gtlTabStatementInstruction : @gtlInstruction { @gtlExpression tabValue } override method @gtlTabStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string outputString { let @gtlData tabValueData = [tabValue eval !context !vars !lib] if tabValueData is == @gtlInt then let @gtlInt tabValueInt = tabValueData as @gtlInt let @uint currentColumn = [outputString currentColumn] if [tabValueInt value] >= 0 then let @uint tabColumn = [[tabValueInt value] uint] if tabColumn > currentColumn then outputString += @string.stringWithSequenceOfCharacters{ !' ' !tabColumn - currentColumn - 1 } end end else error tabValueData : "int expected" end } #-----------------------------------------------------------------------------* # template instructions : variables #-----------------------------------------------------------------------------* class @gtlVariablesInstruction : @gtlInstruction { @bool shortDisplay } method @gtlVariablesInstruction displayShort ?let @gtlData vars { cast vars case == @gtlStruct variableMap: for (name variable) in [variableMap value] do message [name string] + " >\n" message [variable desc !4] end else error self : "INTERNAL ERROR. a variable map should be a @gtlStruct" end } method @gtlVariablesInstruction displayLong ?let @gtlData vars { let @string delimitor = @string.stringWithSequenceOfCharacters{!'=' !79 } + "\n" let @string varDelim = @string.stringWithSequenceOfCharacters{!'-' !79 } + "\n" let @string separator = @string.stringWithSequenceOfCharacters{!'=' !17 } message separator + " Variables " + separator + "= Displayed from " + separator + "\n" message [where locationString] + "\n" message delimitor cast vars case == @gtlStruct variableMap: for (name variable) in [variableMap value] do message varDelim message [name string] + "\n" message varDelim message [variable desc !0] end else error self : "INTERNAL ERROR. a variable map should be a @gtlStruct" end message delimitor } override method @gtlVariablesInstruction execute ?!@gtlContext unused context ?!@gtlData vars ?!@library unused lib ?!@string unused outputString { if shortDisplay then [self displayShort !vars] else [self displayLong !vars] end } #-----------------------------------------------------------------------------* # template instructions : libraries #-----------------------------------------------------------------------------* class @gtlLibrariesInstruction : @gtlInstruction {} override method @gtlLibrariesInstruction execute ?!@gtlContext unused context ?!@gtlData unused vars ?!@library lib ?!@string unused outputString { let @string delimitor = @string.stringWithSequenceOfCharacters{!'=' !79 } + "\n" let @string varDelim = @string.stringWithSequenceOfCharacters{!'-' !79 } + "\n" let @string separator = @string.stringWithSequenceOfCharacters{!'=' !17 } message separator + " Libraries " + separator + "= Displayed from " + separator + "\n" message [where locationString] + "\n" message delimitor message " Functions \n" message varDelim @uint lineSize = 0 for (name *) in [lib funcMap] do if lineSize + [[name string] length] > 75 then lineSize = 0 message "\n" end message [name string] lineSize += [[name string] length] between message ", " lineSize += 2 after message "\n" end message delimitor message " Getters \n" message varDelim lineSize = 0 for (name *) in [lib getterMap] do if lineSize + [[name string] length] > 75 then lineSize = 0 message "\n" end message [name string] lineSize += [[name string] length] between message ", " lineSize += 2 after message "\n" end message delimitor message " Setters \n" message varDelim lineSize = 0 for (name *) in [lib setterMap] do if lineSize + [[name string] length] > 75 then lineSize = 0 message "\n" end message [name string] lineSize += [[name string] length] between message ", " lineSize += 2 after message "\n" end message delimitor message " Templates \n" message varDelim lineSize = 0 for (name *) in [lib templateMap] do if lineSize + [[name string] length] > 75 then lineSize = 0 message "\n" end message [name string] lineSize += [[name string] length] between message ", " lineSize += 2 after message "\n" end message delimitor } #-----------------------------------------------------------------------------* # template instructions : [!target setter : ] #-----------------------------------------------------------------------------* class @gtlSetterCallInstruction : @gtlInstruction { @gtlVarPath target @lstring setterName @gtlExpressionList arguments } override method @gtlSetterCallInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library lib ?!@string unused outputString { @gtlDataList dataArguments = .emptyList for () in arguments do dataArguments += ![expression eval !context !vars !lib] end @gtlData targetData = [target get !context !vars !lib] [!?targetData performSetter !setterName !dataArguments !context !lib] [target set !context !?vars !lib !targetData] } #-----------------------------------------------------------------------------* # template instructions : input #-----------------------------------------------------------------------------* class @gtlInputStatementInstruction : @gtlInstruction { @gtlArgumentList formalArguments } override method @gtlInputStatementInstruction execute ?!@gtlContext context ?!@gtlData vars ?!@library unused lib ?!@string unused outputString { for (typed type name) in formalArguments do [!?context popFirstInputArg !name ?let @gtlData arg] if typed then if type != [arg dynamicType] then error arg : "mistyped argument, " + [[arg dynamicType] typeName] + " provided" error name : [type typeName] + " expected" end end [!?vars setStructField !name !arg] end }