From: <bi...@us...> - 2014-10-31 19:05:24
|
Revision: 10795 http://sourceforge.net/p/oorexx/code-0/10795 Author: bigrixx Date: 2014-10-31 19:05:18 +0000 (Fri, 31 Oct 2014) Log Message: ----------- [#654] Add an instruction that is the inverse of EXPOSE Modified Paths: -------------- main/trunk/CMakeLists.txt main/trunk/api/oorexxerrors.h main/trunk/interpreter/behaviour/ClassTypeCodes.h main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp main/trunk/interpreter/behaviour/PrimitiveClasses.xml main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp main/trunk/interpreter/execution/RexxActivation.cpp main/trunk/interpreter/execution/RexxActivation.hpp main/trunk/interpreter/execution/RexxLocalVariables.cpp main/trunk/interpreter/execution/RexxLocalVariables.hpp main/trunk/interpreter/instructions/ExposeInstruction.hpp main/trunk/interpreter/messages/RexxErrorCodes.h main/trunk/interpreter/messages/RexxMessageNumbers.h main/trunk/interpreter/messages/errnums.xml main/trunk/interpreter/messages/rexxmsg.xml main/trunk/interpreter/parser/InstructionParser.cpp main/trunk/interpreter/parser/KeywordConstants.cpp main/trunk/interpreter/parser/LanguageParser.cpp main/trunk/interpreter/parser/LanguageParser.hpp main/trunk/interpreter/parser/Token.hpp main/trunk/interpreter/platform/unix/rexx.cat main/trunk/interpreter/platform/windows/winmsgtb.rc Added Paths: ----------- main/trunk/interpreter/instructions/UseLocalInstruction.cpp main/trunk/interpreter/instructions/UseLocalInstruction.hpp Modified: main/trunk/CMakeLists.txt =================================================================== --- main/trunk/CMakeLists.txt 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/CMakeLists.txt 2014-10-31 19:05:18 UTC (rev 10795) @@ -642,6 +642,7 @@ ${build_instructions_dir}/ThenInstruction.cpp ${build_instructions_dir}/TraceInstruction.cpp ${build_instructions_dir}/UseInstruction.cpp + ${build_instructions_dir}/UseLocalInstruction.cpp ${build_instructions_dir}/WhenCaseInstruction.cpp) set (parser_sources ${build_parser_dir}/Clause.cpp ${build_parser_dir}/KeywordConstants.cpp Modified: main/trunk/api/oorexxerrors.h =================================================================== --- main/trunk/api/oorexxerrors.h 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/api/oorexxerrors.h 2014-10-31 19:05:18 UTC (rev 10795) @@ -174,6 +174,7 @@ #define Rexx_Error_Symbol_expected_annotation_type 20924 #define Rexx_Error_Symbol_expected_form 20925 #define Rexx_Error_Symbol_expected_delegate 20926 +#define Rexx_Error_Symbol_expected_use_local 20927 #define Rexx_Error_Invalid_data 21000 #define Rexx_Error_Invalid_data_user_defined 21900 #define Rexx_Error_Invalid_data_nop 21901 @@ -638,6 +639,7 @@ #define Rexx_Error_Translation_missing_annotation_target 99945 #define Rexx_Error_Translation_delegate_method 99946 #define Rexx_Error_Translation_delegate_attribute 99947 +#define Rexx_Error_Translation_use_local_compound 99948 #endif Modified: main/trunk/interpreter/behaviour/ClassTypeCodes.h =================================================================== --- main/trunk/interpreter/behaviour/ClassTypeCodes.h 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/behaviour/ClassTypeCodes.h 2014-10-31 19:05:18 UTC (rev 10795) @@ -205,46 +205,47 @@ T_ThenInstruction = 143, T_TraceInstruction = 144, T_UseInstruction = 145, - T_ClassDirective = 146, - T_LibraryDirective = 147, - T_RequiresDirective = 148, - T_CompoundElement = 149, - T_ParseTrigger = 150, - T_ProgramSource = 151, - T_ArrayProgramSource = 152, - T_BufferProgramSource = 153, - T_FileProgramSource = 154, - T_NumberArray = 155, - T_ClassResolver = 156, - T_QualifiedFunction = 157, + T_UseLocalInstruction = 146, + T_ClassDirective = 147, + T_LibraryDirective = 148, + T_RequiresDirective = 149, + T_CompoundElement = 150, + T_ParseTrigger = 151, + T_ProgramSource = 152, + T_ArrayProgramSource = 153, + T_BufferProgramSource = 154, + T_FileProgramSource = 155, + T_NumberArray = 156, + T_ClassResolver = 157, + T_QualifiedFunction = 158, - T_Last_Internal_Class = 157, + T_Last_Internal_Class = 158, - T_First_Transient_Class = 158, + T_First_Transient_Class = 159, - T_Memory = 158, - T_InternalStack = 159, - T_LiveStack = 160, - T_PushThroughStack = 161, - T_Activity = 162, - T_Activation = 163, - T_NativeActivation = 164, - T_ActivationFrameBuffer = 165, - T_Envelope = 166, - T_LanguageParser = 167, - T_Clause = 168, - T_Token = 169, - T_DoBlock = 170, - T_InterpreterInstance = 171, - T_SecurityManager = 172, - T_CommandHandler = 173, - T_MapBucket = 174, - T_MapTable = 175, - T_TrapHandler = 176, + T_Memory = 159, + T_InternalStack = 160, + T_LiveStack = 161, + T_PushThroughStack = 162, + T_Activity = 163, + T_Activation = 164, + T_NativeActivation = 165, + T_ActivationFrameBuffer = 166, + T_Envelope = 167, + T_LanguageParser = 168, + T_Clause = 169, + T_Token = 170, + T_DoBlock = 171, + T_InterpreterInstance = 172, + T_SecurityManager = 173, + T_CommandHandler = 174, + T_MapBucket = 175, + T_MapTable = 176, + T_TrapHandler = 177, - T_Last_Transient_Class = 176, - T_Last_Primitive_Class = 176, - T_Last_Class_Type = 176, + T_Last_Transient_Class = 177, + T_Last_Primitive_Class = 177, + T_Last_Class_Type = 177, } ClassTypeCode; Modified: main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h =================================================================== --- main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h 2014-10-31 19:05:18 UTC (rev 10795) @@ -195,6 +195,7 @@ #define TheThenInstructionBehaviour (&RexxBehaviour::primitiveBehaviours[T_ThenInstruction]) #define TheTraceInstructionBehaviour (&RexxBehaviour::primitiveBehaviours[T_TraceInstruction]) #define TheUseInstructionBehaviour (&RexxBehaviour::primitiveBehaviours[T_UseInstruction]) +#define TheUseLocalInstructionBehaviour (&RexxBehaviour::primitiveBehaviours[T_UseLocalInstruction]) #define TheClassDirectiveBehaviour (&RexxBehaviour::primitiveBehaviours[T_ClassDirective]) #define TheLibraryDirectiveBehaviour (&RexxBehaviour::primitiveBehaviours[T_LibraryDirective]) #define TheRequiresDirectiveBehaviour (&RexxBehaviour::primitiveBehaviours[T_RequiresDirective]) Modified: main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp =================================================================== --- main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -205,6 +205,7 @@ RexxBehaviour(T_ThenInstruction, (PCPPM *)RexxObject::operatorMethods), RexxBehaviour(T_TraceInstruction, (PCPPM *)RexxObject::operatorMethods), RexxBehaviour(T_UseInstruction, (PCPPM *)RexxObject::operatorMethods), + RexxBehaviour(T_UseLocalInstruction, (PCPPM *)RexxObject::operatorMethods), RexxBehaviour(T_ClassDirective, (PCPPM *)RexxObject::operatorMethods), RexxBehaviour(T_LibraryDirective, (PCPPM *)RexxObject::operatorMethods), RexxBehaviour(T_RequiresDirective, (PCPPM *)RexxObject::operatorMethods), Modified: main/trunk/interpreter/behaviour/PrimitiveClasses.xml =================================================================== --- main/trunk/interpreter/behaviour/PrimitiveClasses.xml 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/behaviour/PrimitiveClasses.xml 2014-10-31 19:05:18 UTC (rev 10795) @@ -194,6 +194,7 @@ <Class id="ThenInstruction" class="RexxInstructionThen" include="ThenInstruction.hpp"/> <Class id="TraceInstruction" class="RexxInstructionTrace" include="TraceInstruction.hpp"/> <Class id="UseInstruction" class="RexxInstructionUse" include="UseInstruction.hpp"/> +<Class id="UseLocalInstruction" class="RexxInstructionUseLocal" include="UseLocalInstruction.hpp"/> <Class id="ClassDirective" class="ClassDirective" include="ClassDirective.hpp"/> <Class id="LibraryDirective" class="LibraryDirective" include="LibraryDirective.hpp"/> Modified: main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp =================================================================== --- main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -139,6 +139,7 @@ #include "ThenInstruction.hpp" #include "TraceInstruction.hpp" #include "UseInstruction.hpp" +#include "UseLocalInstruction.hpp" #include "ClassDirective.hpp" #include "LibraryDirective.hpp" #include "RequiresDirective.hpp" @@ -632,6 +633,9 @@ objectPtr = ::new (objectLoc) RexxInstructionUse(RESTOREIMAGE); virtualFunctionTable[T_UseInstruction] = getVftPointer(objectLoc); + objectPtr = ::new (objectLoc) RexxInstructionUseLocal(RESTOREIMAGE); + virtualFunctionTable[T_UseLocalInstruction] = getVftPointer(objectLoc); + objectPtr = ::new (objectLoc) ClassDirective(RESTOREIMAGE); virtualFunctionTable[T_ClassDirective] = getVftPointer(objectLoc); Modified: main/trunk/interpreter/execution/RexxActivation.cpp =================================================================== --- main/trunk/interpreter/execution/RexxActivation.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/execution/RexxActivation.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -1187,6 +1187,35 @@ /** + * Turn on autoexpose as the result of a USE LOCAL instruction. + * + * @param variables The list of variables to declose as local + * variables. + * @param count The variable count. + */ +void RexxActivation::autoExpose(RexxVariableBase **variables, size_t count) +{ + // we just request the value for each of these variables now, which will + // force them to be created as local variables. + for (size_t i = 0; i < count; i++) + { + variables[i]->getRealValue(this); + } + + // now explicitly make RC, RESULT, SIGL, SELF, and SUPER local + getLocalVariable(GlobalNames::SELF, VARIABLE_SELF); + getLocalVariable(GlobalNames::SUPER, VARIABLE_SUPER); + getLocalVariable(GlobalNames::RC, VARIABLE_RC); + getLocalVariable(GlobalNames::SIGL, VARIABLE_SIGL); + getLocalVariable(GlobalNames::RESULT, VARIABLE_RESULT); + + // now switch modes with the local variables so that every new variable + // is created as an object variable. + settings.localVariables.setAutoExpose(getObjectVariables()); +} + + +/** * Process a forward instruction. * * @param target The target object. Modified: main/trunk/interpreter/execution/RexxActivation.hpp =================================================================== --- main/trunk/interpreter/execution/RexxActivation.hpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/execution/RexxActivation.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -173,6 +173,7 @@ void exitFrom(RexxObject *); void procedureExpose(RexxVariableBase **variables, size_t count); void expose(RexxVariableBase **variables, size_t count); + void autoExpose(RexxVariableBase **variables, size_t count); void setTrace(const TraceSetting &); void setTrace(RexxString *); void raise(RexxString *, RexxObject *, RexxString *, RexxObject *, RexxObject *, DirectoryClass *); Modified: main/trunk/interpreter/execution/RexxLocalVariables.cpp =================================================================== --- main/trunk/interpreter/execution/RexxLocalVariables.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/execution/RexxLocalVariables.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -172,7 +172,22 @@ } + /** + * Enable auto exposing of variables. This will switch lookup of + * variables on the first reference to perform an implicit + * expose operation. + * + * @param ov The object variables from the current scope used + * for the expose operation. + */ +void RexxLocalVariables::setAutoExpose(VariableDictionary *ov) +{ + objectVariables = ov; +} + + +/** * Create a local variable object of the given name and store * it at the given location. * @@ -210,29 +225,85 @@ createDictionary(); } - // retrieve this from the variable dictionary now, which will create - // the item we need. - return dictionary->getVariable(name); + // if we're not auto exposing, just lookup the variable which will also + // create it. + if (!autoExpose()) + { + // retrieve this from the variable dictionary now, which will create + // the item we need. + return dictionary->getVariable(name); + } + else + { + // this might have been previously created. check the dictionary + // first, then create if necessary + RexxVariable *variable = dictionary->resolveVariable(name); + if (variable != OREF_NULL) + { + return variable; + } + + // get the variable from the object variable dictionary + // and add it to the local dictionary. + variable = objectVariables->getVariable(name); + dictionary->addVariable(name, variable); + return variable; + } } else { - RexxVariable *variable; - // if we've had to create a dictionary for this because of - // prior dynamic access, then we need to retrieve the - // variable from the dictionary. - if (dictionary != OREF_NULL) + // normal local variable lookup, just create the local variable + // and return it. + if (!autoExpose()) { - variable = dictionary->getVariable(name); + RexxVariable *variable; + // if we've had to create a dictionary for this because of + // prior dynamic access, then we need to retrieve the + // variable from the dictionary. + if (dictionary != OREF_NULL) + { + variable = dictionary->getVariable(name); + } + // we've already had a cache miss, so we're creating a variable. + else + { + variable = owner->newLocalVariable(name); + } + // fill in the cache slot for the next lookup and return + // the new variable. + locals[index] = variable; + return variable; } - // we've already had a cache miss, so we're creating a variable. else { - variable = owner->newLocalVariable(name); + // if we've had to create a dictionary for this because of + // prior dynamic access, then we need to retrieve the + // variable from the dictionary. + if (dictionary != OREF_NULL) + { + // this might have been previously created. check the dictionary + // first, then create if necessary + RexxVariable *variable = dictionary->resolveVariable(name); + if (variable != OREF_NULL) + { + return variable; + } + } + + // get the variable from the object variable dictionary + RexxVariable *variable = objectVariables->getVariable(name); + // if we've had to create a dictionary for this because of + // prior dynamic access, then we need to retrieve the + // variable from the dictionary. + if (dictionary != OREF_NULL) + { + dictionary->addVariable(name, variable); + } + // fill in the cache slot for the next lookup and return + // the new variable. + locals[index] = variable; + return variable; } - // fill in the cache slot for the next lookup and return - // the new variable. - locals[index] = variable; - return variable; } } @@ -276,37 +347,90 @@ createDictionary(); } - // have the dictionary create this for us - return dictionary->getStemVariable(name); + // if we're not auto exposing, just lookup the variable which will also + // create it. + if (!autoExpose()) + { + // retrieve this from the variable dictionary now, which will create + // the item we need. + + // have the dictionary create this for us + return dictionary->getStemVariable(name); + } + else + { + // this might have been previously created. check the dictionary + // first, then create if necessary + RexxVariable *variable = dictionary->resolveVariable(name); + if (variable != OREF_NULL) + { + return variable; + } + + // get the variable from the object variable dictionary + // and add it to the local dictionary. + variable = objectVariables->getStemVariable(name); + dictionary->addVariable(name, variable); + return variable; + } } else { - // if we've had to create a dictionary for this because of - // prior dynamic access, then we need to retrieve the - // variable from the dictionary. + if (!autoExpose()) + { + // if we've had to create a dictionary for this because of + // prior dynamic access, then we need to retrieve the + // variable from the dictionary. - RexxVariable *variable; - if (dictionary != OREF_NULL) - { - // create from the dictionary and add this to the cache at - // the target location. - variable = dictionary->getStemVariable(name); - locals[index] = variable; + RexxVariable *variable; + if (dictionary != OREF_NULL) + { + // create from the dictionary and add this to the cache at + // the target location. + variable = dictionary->getStemVariable(name); + locals[index] = variable; + } + else + { + // create a new variable from the local context and + // add it to the cache. + variable = owner->newLocalVariable(name); + locals[index] = variable; + + // stem variables are initialized as soon as they + // are created, using a stem object with the same name. + StemClass *stemtable = new StemClass(name); + variable->set(stemtable); + } + // and return the new variable + return variable; } else { - // create a new variable from the local context and - // add it to the cache. - variable = owner->newLocalVariable(name); + // if we've had to create a dictionary for this because of + // prior dynamic access, then we need to retrieve the + // variable from the dictionary. + if (dictionary != OREF_NULL) + { + // this might have been previously created. check the dictionary + // first, then create if necessary + RexxVariable *variable = dictionary->resolveVariable(name); + if (variable != OREF_NULL) + { + return variable; + } + } + // get the variable from the object variable dictionary + RexxVariable *variable = objectVariables->getStemVariable(name); + if (dictionary != OREF_NULL) + { + dictionary->addVariable(name, variable); + } + // fill in the cache slot for the next lookup and return + // the new variable. locals[index] = variable; - - // stem variables are initialized as soon as they - // are created, using a stem object with the same name. - StemClass *stemtable = new StemClass(name); - variable->set(stemtable); + return variable; } - // and return the new variable - return variable; } } Modified: main/trunk/interpreter/execution/RexxLocalVariables.hpp =================================================================== --- main/trunk/interpreter/execution/RexxLocalVariables.hpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/execution/RexxLocalVariables.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -88,7 +88,7 @@ /* NOTE: we add one because the size is actually the index */ /* number of the last variable in the cache. The zero-th */ /* element is used to trigger cache lookup failures. */ - inline void init(RexxActivation *creator, size_t poolSize) { owner = creator; size = poolSize + 1; dictionary = OREF_NULL; flags.reset(); } + inline void init(RexxActivation *creator, size_t poolSize) { owner = creator; size = poolSize + 1; dictionary = OREF_NULL; objectVariables = OREF_NULL; flags.reset(); } inline void setFrame(RexxInternalObject **frame) { locals = (RexxVariable **)frame; @@ -136,6 +136,7 @@ } void updateVariable(RexxVariable*); + void setAutoExpose(VariableDictionary *ov); inline RexxVariable *get(size_t index) { return locals[index]; } inline RexxVariable *find(RexxString *name, size_t index) @@ -155,6 +156,7 @@ inline void setNested() { flags.set(NESTED_INTERNAL); } inline void clearNested() { flags.reset(NESTED_INTERNAL); } inline bool isNested() { return flags[NESTED_INTERNAL]; } + inline bool autoExpose() { return objectVariables != OREF_NULL; } inline void procedure(RexxActivation *activation) { owner = activation; dictionary = OREF_NULL; clearNested(); } inline void setDictionary(VariableDictionary *dict) { dictionary = dict; } @@ -168,6 +170,7 @@ size_t size; // size of the expstack RexxActivation *owner; // the owning activation RexxVariable **locals; // the frame of local variables - VariableDictionary *dictionary; // dictionary used for dynamic lookups + VariableDictionary *dictionary; // dictionary used for dynamic lookups + VariableDictionary *objectVariables; // dictionary used for automatic expose operations }; #endif Modified: main/trunk/interpreter/instructions/ExposeInstruction.hpp =================================================================== --- main/trunk/interpreter/instructions/ExposeInstruction.hpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/instructions/ExposeInstruction.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -46,7 +46,8 @@ #include "RexxInstruction.hpp" -class RexxInstructionExpose : public RexxInstruction { +class RexxInstructionExpose : public RexxInstruction +{ public: RexxInstructionExpose(size_t, QueueClass *); inline RexxInstructionExpose(RESTORETYPE restoreType) { ; }; Added: main/trunk/interpreter/instructions/UseLocalInstruction.cpp =================================================================== --- main/trunk/interpreter/instructions/UseLocalInstruction.cpp (rev 0) +++ main/trunk/interpreter/instructions/UseLocalInstruction.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -0,0 +1,134 @@ +/*----------------------------------------------------------------------------*/ +/* */ +/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */ +/* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved. */ +/* */ +/* This program and the accompanying materials are made available under */ +/* the terms of the Common Public License v1.0 which accompanies this */ +/* distribution. A copy is also available at the following address: */ +/* http://www.oorexx.org/license.html */ +/* */ +/* Redistribution and use in source and binary forms, with or */ +/* without modification, are permitted provided that the following */ +/* conditions are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in */ +/* the documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the name of Rexx Language Association nor the names */ +/* of its contributors may be used to endorse or promote products */ +/* derived from this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */ +/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/*----------------------------------------------------------------------------*/ +/******************************************************************************/ +/* REXX Translator */ +/* */ +/* Use Local instruction class */ +/* */ +/******************************************************************************/ +#include "RexxCore.h" +#include "RexxActivation.hpp" +#include "QueueClass.hpp" +#include "UseLocalInstruction.hpp" +#include "ExpressionBaseVariable.hpp" + +/** + * Complete construction of a USE LOCAL instruction. + * + * @param varCount The count of variables to expose. + * @param variable_list + * The queue of the variable retrievers (in reverse order). + */ +RexxInstructionUseLocal::RexxInstructionUseLocal(size_t varCount, QueueClass *variable_list) +{ + // get the variable size + variableCount = varCount; + // now copy all of the retriever references from the queue, back to front. + initializeObjectArray(varCount, variables, RexxVariableBase, variable_list); +} + + +/** + * Perform garbage collection on a live object. + * + * @param liveMark The current live mark. + */ +void RexxInstructionUseLocal::live(size_t liveMark) +{ + // must be first one marked + memory_mark(nextInstruction); + memory_mark_array(variableCount, variables); +} + + +/** + * Perform generalized live marking on an object. This is + * used when mark-and-sweep processing is needed for purposes + * other than garbage collection. + * + * @param reason The reason for the marking call. + */ +void RexxInstructionUseLocal::liveGeneral(MarkReason reason) +{ + // must be first one marked + memory_mark_general(nextInstruction); + memory_mark_general_array(variableCount, variables); +} + + +/** + * Flatten a source object. + * + * @param envelope The envelope that will hold the flattened object. + */ +void RexxInstructionUseLocal::flatten(Envelope *envelope) +{ + setUpFlatten(RexxInstructionUseLocal) + + flattenRef(nextInstruction); + flattenArrayRefs(variableCount, variables); + + cleanUpFlatten +} + + +/** + * Execute a USE LOCAL instruction. + * + * @param context The current execution context. + * @param stack The current evaluation stack. + */ +void RexxInstructionUseLocal::execute(RexxActivation *context, ExpressionStack *stack) +{ + // standard trace on entry. + context->traceInstruction(this); + + // not allowed in a method context. + if (!context->inMethod()) + { + reportException(Error_Translation_expose); + } + + // the context processeses these + context->autoExpose(variables, variableCount); + + // and standare debug pause. + context->pauseInstruction(); +} + + Property changes on: main/trunk/interpreter/instructions/UseLocalInstruction.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: main/trunk/interpreter/instructions/UseLocalInstruction.hpp =================================================================== --- main/trunk/interpreter/instructions/UseLocalInstruction.hpp (rev 0) +++ main/trunk/interpreter/instructions/UseLocalInstruction.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -0,0 +1,67 @@ +/*----------------------------------------------------------------------------*/ +/* */ +/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */ +/* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved. */ +/* */ +/* This program and the accompanying materials are made available under */ +/* the terms of the Common Public License v1.0 which accompanies this */ +/* distribution. A copy is also available at the following address: */ +/* http://www.oorexx.org/license.html */ +/* */ +/* Redistribution and use in source and binary forms, with or */ +/* without modification, are permitted provided that the following */ +/* conditions are met: */ +/* */ +/* Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in */ +/* the documentation and/or other materials provided with the distribution. */ +/* */ +/* Neither the name of Rexx Language Association nor the names */ +/* of its contributors may be used to endorse or promote products */ +/* derived from this software without specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ +/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */ +/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/*----------------------------------------------------------------------------*/ +/******************************************************************************/ +/* REXX Kernel UseLocalInstruction.hpp */ +/* */ +/* USE LOCAL instruction */ +/* */ +/******************************************************************************/ +#ifndef Included_RexxInstructionUseLocal +#define Included_RexxInstructionUseLocal + +#include "RexxInstruction.hpp" + +class RexxInstructionUseLocal : public RexxInstruction +{ + public: + RexxInstructionUseLocal(size_t, QueueClass *); + inline RexxInstructionUseLocal(RESTORETYPE restoreType) { ; }; + + virtual void live(size_t); + virtual void liveGeneral(MarkReason reason); + virtual void flatten(Envelope*); + + virtual void execute(RexxActivation *, ExpressionStack *); + +protected: + + size_t variableCount; // number of variables to force as locals + RexxVariableBase *variables[1]; // list of variables for to force as locals +}; +#endif + Property changes on: main/trunk/interpreter/instructions/UseLocalInstruction.hpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: main/trunk/interpreter/messages/RexxErrorCodes.h =================================================================== --- main/trunk/interpreter/messages/RexxErrorCodes.h 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/messages/RexxErrorCodes.h 2014-10-31 19:05:18 UTC (rev 10795) @@ -176,6 +176,7 @@ Error_Symbol_expected_annotation_type = 20924, Error_Symbol_expected_form = 20925, Error_Symbol_expected_delegate = 20926, +Error_Symbol_expected_use_local = 20927, Error_Invalid_data = 21000, Error_Invalid_data_user_defined = 21900, Error_Invalid_data_nop = 21901, @@ -640,6 +641,7 @@ Error_Translation_missing_annotation_target = 99945, Error_Translation_delegate_method = 99946, Error_Translation_delegate_attribute = 99947, +Error_Translation_use_local_compound = 99948, Error_at_line = 101000, Message_Translations_error = 101001, Message_Translations_running = 101002, Modified: main/trunk/interpreter/messages/RexxMessageNumbers.h =================================================================== --- main/trunk/interpreter/messages/RexxMessageNumbers.h 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/messages/RexxMessageNumbers.h 2014-10-31 19:05:18 UTC (rev 10795) @@ -683,6 +683,8 @@ #define Error_Translation_delegate_method_msg 774 #define Error_Symbol_expected_delegate_msg 775 #define Error_Translation_delegate_attribute_msg 776 +#define Error_Symbol_expected_use_local_msg 777 +#define Error_Translation_use_local_compound_msg 778 #endif Modified: main/trunk/interpreter/messages/errnums.xml =================================================================== --- main/trunk/interpreter/messages/errnums.xml 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/messages/errnums.xml 2014-10-31 19:05:18 UTC (rev 10795) @@ -859,6 +859,12 @@ <para>Symbol expected after the DELEGATE keyword.</para> </listitem> </varlistentry> +<varlistentry> +<term>927</term> +<listitem> +<para>Symbol expected after USE LOCAL.</para> +</listitem> +</varlistentry> </variablelist> </section> <section id="ERR21"> @@ -3922,6 +3928,12 @@ <para>Delegate attributes cannot have a method body.</para> </listitem> </varlistentry> +<varlistentry> +<term>948</term> +<listitem> +<para>USE LOCAL cannot process compound variables; found "<emphasis role="italic">variable</emphasis>".</para> +</listitem> +</varlistentry> </variablelist> </section> </section> Modified: main/trunk/interpreter/messages/rexxmsg.xml =================================================================== --- main/trunk/interpreter/messages/rexxmsg.xml 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/messages/rexxmsg.xml 2014-10-31 19:05:18 UTC (rev 10795) @@ -1238,6 +1238,15 @@ <SymbolicName>Error_Symbol_expected_delegate</SymbolicName> <Text>Symbol expected after the DELEGATE keyword.</Text> </SubMessage> + <SubMessage> + <Code>20</Code> + <Subcode>927</Subcode> + <MessageNumber>777</MessageNumber> + <Component>Rexx</Component> + <Severity>Warning</Severity> + <SymbolicName>Error_Symbol_expected_use_local</SymbolicName> + <Text>Symbol expected after USE LOCAL.</Text> + </SubMessage> </Subcodes> </Message> <Message> @@ -5574,6 +5583,15 @@ <SymbolicName>Error_Translation_delegate_attribute</SymbolicName> <Text>Delegate attributes cannot have a method body.</Text> </SubMessage> + <SubMessage> + <Code>99</Code> + <Subcode>948</Subcode> + <MessageNumber>778</MessageNumber> + <Component>Rexx</Component> + <Severity>Warning</Severity> + <SymbolicName>Error_Translation_use_local_compound</SymbolicName> + <Text>USE LOCAL cannot process compound variables; found <q><Sub position="1" name="variable"/></q>.</Text> + </SubMessage> </Subcodes> </Message> <Message> Modified: main/trunk/interpreter/parser/InstructionParser.cpp =================================================================== --- main/trunk/interpreter/parser/InstructionParser.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/parser/InstructionParser.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -86,6 +86,7 @@ #include "RaiseInstruction.hpp" #include "TraceInstruction.hpp" #include "UseInstruction.hpp" +#include "UseLocalInstruction.hpp" #include "CallInstruction.hpp" /* call/signal instructions */ #include "SignalInstruction.hpp" @@ -1736,6 +1737,81 @@ /** + * Parse and create a new USE LOCAL instruction + * + * @return The configured instruction instance. + */ +RexxInstruction *LanguageParser::useLocalNew() +{ + // not valid in an interpret + if (isInterpret()) + { + syntaxError(Error_Translation_expose_interpret); + } + + // validate the placement at the beginning of the code block... + // the rules are the same as with EXPOSE. + isExposeValid(); + + // switch on auto expose tracking + autoExpose(); + + // process the variable list and create an instruction from this. + // There are enough differences from EXPOSE/DROP/PROCEDURE that it is + // easier doing this here. + size_t variableCount = 0; + + // the next real token is the start of the list (after the + // space following the keyword instruction. + RexxToken *token = nextReal(); + + // while not at the end of the clause, process a list of variables. Note + // that the variable list is optional. + while (!token->isEndOfClause()) + { + // generally, these are symbols, but not all symbols are variables. + if (token->isSymbol()) + { + // non-variable symbol? + if (token->isSubtype(SYMBOL_CONSTANT)) + { + syntaxError(Error_Invalid_variable_number, token); + } + // the dummy period + else if (token->isSubtype(SYMBOL_DUMMY)) + { + syntaxError(Error_Invalid_variable_period, token); + } + // we only allow simple variables or stems to be declared local + else if (token->isSubtype(SYMBOL_COMPOUND)) + { + syntaxError(Error_Translation_use_local_compound, token); + } + + // ok, get a retriever for the variable and push it on the stack. + pushSubTerm(addVariable(token)); + // the GUARD instruction also needs to understand about locals, + // so record this as an explicit local + localVariable(token->value()); + // update our return value. + variableCount++; + } + // something unrecognized...we need to issue the message for the instruction. + else + { + syntaxError(Error_Symbol_expected_use_local); + } + // and see if we have more variables + token = nextReal(); + } + + RexxInstruction *newObject = new_variable_instruction(USE_LOCAL, UseLocal, variableCount, RexxObject *); + ::new ((void *)newObject) RexxInstructionUseLocal(variableCount, subTerms); + return newObject; +} + + +/** * Parse and create a new FORWARD instruction object. * * @return The new instruction object. @@ -3561,6 +3637,7 @@ return newObject; } + /** * Parse a USE STRICT ARG instruction. * @@ -3575,6 +3652,12 @@ RexxToken *token = nextReal(); InstructionSubKeyword subkeyword = token->subKeyword(); + // check for USE LOCAL first. we really just handle the USE ARG in here + if (subkeyword == SUBKEY_LOCAL) + { + return useLocalNew(); + } + if (subkeyword == SUBKEY_STRICT) { token = nextReal(); // skip over the token Modified: main/trunk/interpreter/parser/KeywordConstants.cpp =================================================================== --- main/trunk/interpreter/parser/KeywordConstants.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/parser/KeywordConstants.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -124,6 +124,7 @@ KeywordEntry("FORM", SUBKEY_FORM), KeywordEntry("FUZZ", SUBKEY_FUZZ), KeywordEntry("LABEL", SUBKEY_LABEL), + KeywordEntry("LOCAL", SUBKEY_LOCAL), KeywordEntry("MESSAGE", SUBKEY_MESSAGE), KeywordEntry("NAME", SUBKEY_NAME), KeywordEntry("OFF", SUBKEY_OFF), Modified: main/trunk/interpreter/parser/LanguageParser.cpp =================================================================== --- main/trunk/interpreter/parser/LanguageParser.cpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/parser/LanguageParser.cpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -410,6 +410,7 @@ memory_mark(strings); memory_mark(guardVariables); memory_mark(exposedVariables); + memory_mark(localVariables); memory_mark(control); memory_mark(terms); memory_mark(subTerms); @@ -455,6 +456,7 @@ memory_mark_general(strings); memory_mark_general(guardVariables); memory_mark_general(exposedVariables); + memory_mark_general(localVariables); memory_mark_general(control); memory_mark_general(terms); memory_mark_general(subTerms); @@ -1040,8 +1042,9 @@ // until we need guard variables, we don't need the table guardVariables = OREF_NULL; - // and we need a new set of exposed variables for each code section - exposedVariables = new_string_table(); + // and we reset the exposed/local variables for each code section + exposedVariables = OREF_NULL; + localVariables = OREF_NULL; // clear the stack accounting fields maxStack = 0; @@ -1715,9 +1718,22 @@ */ bool LanguageParser::isExposed(RexxString *varName) { - return exposedVariables != OREF_NULL && exposedVariables->hasIndex(varName); + // if we had an explicit EXPOSE instruction, check if this was listed + if (exposedVariables != OREF_NULL) + { + return exposedVariables->hasIndex(varName); + } + // had a USE ARG instruction specified? Variable is exposed + + else if (localVariables != OREF_NULL) + { + return !localVariables->hasIndex(varName); + } + // neither situation, not an exposed variable + return false; } + /** * Perform a variable capture operation if we're * evaluating a GUARD WHEN expression. @@ -1937,12 +1953,45 @@ */ void LanguageParser::expose(RexxString *name ) { - + // create the table on the first expose + if (exposedVariables == OREF_NULL) + { + exposedVariables = new_string_table(); + } exposedVariables->put(name, name); } /** + * We have a USE LOCAL specified, so turn on the auto expose. + */ +void LanguageParser::autoExpose() +{ + localVariables = new_string_table(); + // add the special local variables to the list + localVariables->put(GlobalNames::SUPER, GlobalNames::SUPER); + localVariables->put(GlobalNames::SELF, GlobalNames::SELF); + localVariables->put(GlobalNames::RC, GlobalNames::RC); + localVariables->put(GlobalNames::RESULT, GlobalNames::RESULT); + localVariables->put(GlobalNames::SIGL, GlobalNames::SIGL); + +} + + +/** + * Add a variable name to the list of explicitly declared to be + * local. + * + * @param name The name of the variable. + */ +void LanguageParser::localVariable(RexxString *name ) +{ + + localVariables->put(name, name); +} + + +/** * Compress all string tokens needed by a group of programs into * a single, common set of strings. It is fairly common * for a program to have duplicate versions of strings Modified: main/trunk/interpreter/parser/LanguageParser.hpp =================================================================== --- main/trunk/interpreter/parser/LanguageParser.hpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/parser/LanguageParser.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -173,6 +173,8 @@ RexxStemVariable *addStem(RexxString *); RexxCompoundVariable *addCompound(RexxString *); void expose(RexxString *); + void localVariable(RexxString *); + void autoExpose(); RexxString *commonString(RexxString *); RexxInternalObject *addText(RexxToken *); RexxVariableBase *addVariable(RexxToken *); @@ -291,6 +293,7 @@ RexxInstruction *thenNew(RexxToken *, RexxInstructionIf *); RexxInstruction *traceNew(); RexxInstruction *useNew(); + RexxInstruction *useLocalNew(); inline void addReference(RexxInternalObject *reference) { calls->addLast(reference); } inline void pushDo(RexxInstruction *i) { control->push(i); } @@ -486,6 +489,7 @@ StringTable *labels; // root of associated label list IdentityTable *guardVariables; // exposed variables in guard list StringTable *exposedVariables; // root of exposed variables list + StringTable *localVariables; // list of explicitly specified local variables ArrayClass *calls; // root of call list size_t currentStack; // current expression stack depth Modified: main/trunk/interpreter/parser/Token.hpp =================================================================== --- main/trunk/interpreter/parser/Token.hpp 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/parser/Token.hpp 2014-10-31 19:05:18 UTC (rev 10795) @@ -247,7 +247,7 @@ KEYWORD_CLASS, KEYWORD_LIBRARY, KEYWORD_REQUIRES, - + KEYWORD_USE_LOCAL, } InstructionKeyword; // instruction subkeyword types @@ -266,6 +266,7 @@ SUBKEY_FORM, SUBKEY_FUZZ, SUBKEY_LINEIN, + SUBKEY_LOCAL, SUBKEY_LOWER, SUBKEY_CASELESS, SUBKEY_NAME, Modified: main/trunk/interpreter/platform/unix/rexx.cat =================================================================== --- main/trunk/interpreter/platform/unix/rexx.cat 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/platform/unix/rexx.cat 2014-10-31 19:05:18 UTC (rev 10795) @@ -1940,7 +1940,13 @@ $ Error_Translation_delegate_attribute 776 Delegate attributes cannot have a method body. +$ Error_Symbol_expected_use_local +777 Symbol expected after USE LOCAL. +$ Error_Translation_use_local_compound +778 USE LOCAL cannot process compound variables; found "&1". + + $ * -------------------------------------------------------------------------- */ $ * -- ================================================== -- */ $ * -- DO NOT CHANGE THIS FILE, ALL CHANGES WILL BE LOST! -- */ Modified: main/trunk/interpreter/platform/windows/winmsgtb.rc =================================================================== --- main/trunk/interpreter/platform/windows/winmsgtb.rc 2014-10-31 19:04:22 UTC (rev 10794) +++ main/trunk/interpreter/platform/windows/winmsgtb.rc 2014-10-31 19:05:18 UTC (rev 10795) @@ -682,6 +682,8 @@ 99946 "Delegate methods cannot have a method body." 20926 "Symbol expected after the DELEGATE keyword." 99947 "Delegate attributes cannot have a method body." + 20927 "Symbol expected after USE LOCAL." + 99948 "USE LOCAL cannot process compound variables; found ""&1""." END |