-- $Id: java_expr_evaluation.ty,v 1.14 10/.0/.2 .1:.1:.4 mrusso Exp $ -- /***************************************************************************/ -- /* Copyright (C) 1997-1999 INRIA Sophia-Antipolis */ -- /* I. Attali, D. Caromel and M. Russo */ -- /* Projet OASIS */ -- /* Rt. des Lucioles, BP 93, */ -- /* F-06902 Sophia Antipolis cedex */ -- /* (+33) 4 92 38 76 31 */ -- /* All rights reserved */ -- /***************************************************************************/ program java_expr_evaluation is use java; use PSP; import sub ( _, _, _ ) , sup ( _, _ ) from arith; import APIMethodOrConstructorCall ( Objects, ClassVariablesL, Ref, Ref |- Identifier, java -> Objects, ClassVariablesL, Insts, ThreadStatus ) from java_api; import evaluateBinaryOperation ( |- Val, Val, BinaryOperator -> Val ) , evaluateUnaryOperation ( |- Val, BinaryOperator -> Val ) , getAttributeOrStaticVariableValue ( Objects, ClassVariablesL, ObjectId |- Identifier -> Val ) , getParameterOrLocalOrStaticVariableValue ( Env, ClassVariablesL, Identifier |- Identifier -> Val ) , getStaticVariableValue ( ClassVariablesL, Identifier |- Identifier -> Val ) , getVariableValue ( Objects, ClassVariablesL, Env, ObjectId |- Identifier -> Val ) from java_evaluate; import getClassDeclaration ( |- OptTypeName -> TypeDeclaration ) , getDirectAncestor ( |- OptTypeName -> OptTypeName ) , isAClass ( Identifier -> Bool ) , getFieldDeclaration ( Objects, OptTypeName, Vals, Bool |- Identifier -> FieldDeclaration, Identifier, Bool ) from java_inheritance; import createExceptionObject ( Objects, ObjectId |- Identifier, ExceptText -> ObjectId, Objects, Insts ) , createObject ( ObjectId |- ObjectNumber, OptTypeName -> Object, ObjectId ) , generateANumberForTheNewObject ( |- Objects -> ObjectNumber ) , getObjectType ( ObjectId |- Objects -> Type ) , getThreadCurrentMethod ( ObjectId |- Objects -> Identifier ) , makeBindedParamList ( Vals |- Parameters -> Pairs ) , makeClosure ( OptTypeName, Vals, ObjectId |- FieldDeclaration -> Clr ) , getInstructionsAndLocalVariables ( Insts, Locs |- Block => Insts, Locs ) from java_object_list; import appendtree ( _, _, _ ) , diff ( _, _ ) , not_eq ( _, _ ) from prolog() ; import newArray ( Type, integer, ObjectId |- Objects -> Objects, ObjectId, Insts ) , newArrayWithValues ( Type, Vals |- Objects -> Objects, ObjectId ) , setArrayElement ( Ref, integer, Val, ObjectId |- Objects -> Objects, Insts ) , getArrayElement ( Ref, integer, ObjectId |- Objects -> Val, Objects, Insts ) from java_array_support; var TVLit: Literal; var TVValue, TVValue1, TVValue2, TVValue3: Val; var TVObjRef: Ref; var TVObjId: ObjectId; var TVIdent, TVClName, TVObjName, TVMethName: Identifier; var TVArgL: SemArguments; var TVArrayInit: ArrayInitializer; set evaluateExpression is --SC: Evaluates an expression. -- --SC: Allowed Expressions: --SC: Literal (Ex: 2), Object reference (#1 or #T3), 'This' keyword, --SC: Variable (varX), Class variable (Math.PI ie ClassName.ClassVarName) -- --JC: Object list, Class variable list, Execution environment (parameters and --JC: local variables), Current executing thread reference, Current object --JC: reference, Execution mode --JC: |- Expression to evaluate --JC: -> Updated object and class variable lists, Updated environment, --JC: New expression (which will be evaluated later), Instruction list to --JC: execute at the next execution step of the current executing thread, --JC: New status of the current executing thread. judgement Objects, ClassVariablesL, Env, ObjectId, ObjectId, Identifier |- SemExpression -> Objects, ClassVariablesL, Env, SemExpression, Insts, ThreadStatus; Literal: --RC: If the expression is a literal, returns it. -- --CS: 101 ObjL, ClVarL, Env, _, _, _ |- TVLit -> ObjL, ClVarL, Env, TVLit, insts[], runnable() ; Reference: --RC: If the expresssion is an object reference, returns it. -- --CS: #T1 or #2 ObjL, ClVarL, Env, _, _, _ |- TVObjRef -> ObjL, ClVarL, Env, TVObjRef, insts[], runnable() ; This: --RC: If the expression is the 'this' keyword returns the Object --RC: represented by the 'this' keyword -- --CS: this ObjL, ClVarL, Env, _, ObjId, _ |- this() -> ObjL, ClVarL, Env, ObjId, insts[], runnable() ; IdentifierInANonStaticMethod: --RC: If the expression (included in a non-static method) is an identifier --RC: gets its value and returns it. -- --CS: varX getVariableValue( ObjL, ClVarL, Env, ObjId |- TVIdent -> Value ) -------------------------------- ObjL, ClVarL, Env, _, ObjId, identifier "none" |- TVIdent -> ObjL, ClVarL, Env, Value, insts[], runnable() ; IdentifierInAStaticMethod: --RC: If the expression (included in a static method) is an identifier, --RC: gets its value and returns it. -- --CS: var1 getParameterOrLocalOrStaticVariableValue( Env, ClVarL, ClName |- TVIdent -> Value ) -------------------------------- ObjL, ClVarL, Env, _, _, ClName |- TVIdent -> ObjL, ClVarL, Env, Value, insts[], runnable() ; provided diff( ClName, identifier "none" ); ConvertAccessToCompAccess: --BSC: Access Expression evaluation -- --RC: Convert an access operator into a comp_access operator. -- --CS: Expression.Ident evaluateExpression( ObjL1, ClVarL1, Env1, OthId, ObjId, Mode |- semAccess(Expr1, Ident) -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OthId, ObjId, Mode |- access(Expr1, Ident) -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL, ThStatus ; ComplexAccessViaNull: --RC: The referenced object has not been created, so its --RC: elements cannot be accessed. So an exception is thrown. --RC: NOTE! This rule will not catch uninitialized local variables (value = empty()) --RC: since this is a STATIC error. -- --CS: null().Identifier createExceptionObject( ObjL1, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- semAccess(null(), _) -> ObjL1_1, ClVarL, Env, empty(), InstL, runnable() ; ComplexAccessToAStaticVariableOrAnAttributeValue: --RC: Retrieves the object attribute or the static variable value. --RC: This object has already been created before this access, so its --RC: reference is known. -- --CS: #i.Ident; getAttributeOrStaticVariableValue( ObjL, ClVarL, TVObjId |- Ident -> Value ) -------------------------------- ObjL, ClVarL, Env, _, _, _ |- semAccess(TVObjId, Ident) -> ObjL, ClVarL, Env, Value, insts[], runnable() ; ComplexAccessToAStaticVariableValue: --RC: Returns the class variable value. -- --CS: Math.PI (i.e. ClName.ClassVariableName) isAClass( TVClName -> true() ) & getStaticVariableValue( ClVarL, TVClName |- ClVarName -> Value ) -------------------------------- ObjL, ClVarL, Env, _, _, _ |- semAccess(TVClName, ClVarName) -> ObjL, ClVarL, Env, Value, insts[], runnable() ; ComplexAccess_IdentifierEvaluation: --RC: The variable is an object name. Gets this object reference. -- --CS: TVObjName.AttrName; isAClass( TVObjName -> false() ) & getVariableValue( ObjL, ClVarL, Env, ObjId |- TVObjName -> TVObjRef ) -------------------------------- ObjL, ClVarL, Env, _, ObjId, _ |- semAccess(TVObjName, AttrName) -> ObjL, ClVarL, Env, semAccess(TVObjRef, AttrName), insts[], runnable() ; ComplexAccess_ExpressionEvaluation: --RC: The left hand member of the access is not null, an object id, or --RC: an identifier. So it is evaluated into a more simple expression --RC: in order to evaluate this access. -- --CS: Expression1.Identifier -- --ESC: Access Expression Evaluation evaluateExpression( ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- Expr1 -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- semAccess(Expr1, Ident) -> ObjL1_1, ClVarL1_1, Env1_1, semAccess(Expr1_1, Ident), InstL, ThStatus ; provided not_eq( Expr1, objectId(_, _) ) & not_eq( Expr1, null() ) & not_eq( Expr1, identifier _ ); ConvertArrayAccessToSemArrayAccess: --BSC: Access Expression evaluation -- --RC: Convert an arrayAccess operator into a semArrayAccess operator. -- --CS: PrimaryNoNewArray [ Expression ] (Primary... is subset of Expr.) evaluateExpression( ObjL, ClVarL, Env, OthId, ObjId, Mode |- semArrayAccess(Expr1, Expr2) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OthId, ObjId, Mode |- arrayAccess(Expr1, Expr2) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; ComplexArrayAccess_ArrayEvaluation: --RC: The array part of the access is not yet a reference (null or object id). --RC: Evaluate it one more step. -- --CS: Expression1[Expression2] evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr1 -> ObjL_1, ClVarL_1, Env_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAccess(Expr1, Expr2) -> ObjL_1, ClVarL_1, Env_1, semArrayAccess(Expr1_1, Expr2), InstL, ThStatus ; provided not_eq( Expr1, objectId(_, _) ) & not_eq( Expr1, null() ); ComplexArrayAccess_IndexEvaluation: --RC: The index part of the access is not yet an integer. Evaluate it one more step. -- --CS: #4[Expression] evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAccess(TVObjRef, Expr) -> ObjL_1, ClVarL_1, Env_1, semArrayAccess(TVObjRef, Expr_1), InstL, ThStatus ; provided not_eq( Expr, integer _ ); ComplexArrayAccess_NullPointer: --RC: The array reference is null. Throw an exception. (Note that this is not --RC: checked until the index has been fully evaluated.) --RC: NOTE! This rule will not catch uninitialized local variables (value = empty()) --RC: since this is a STATIC error. -- --CS: null()[7] createExceptionObject( ObjL, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, _, _ |- semArrayAccess(null(), integer _) -> ObjL_1, ClVarL, Env, empty(), InstL, runnable() ; ComplexArrayAccess_GetElement: --RC: Retrieves the value at the indicated index. Throws an exception if the index --RC: is out of bounds. -- --CS: #i[7]; getArrayElement( TVObjId, i, OThId |- ObjL -> Value, ObjL_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, _, _ |- semArrayAccess(TVObjId, integer i) -> ObjL_1, ClVarL, Env, Value, InstL, runnable() ; NewObjectCreation: --RC: Creates an instance of the given class and adds this instance to the --RC: object list that contains all the objects created by the current --RC: interpreted program. The next execution step of the current --RC: executing thread will be the constructor call. -- --CS: new Thread(); generateANumberForTheNewObject( |- ObjL1 -> i ) & createObject( OThId |- i, TVClName -> Obj, ObjId ) & appendtree( ObjL1, objects[Obj], ObjL1_1 ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- newObject(new(), TVClName, ArgL, fieldDeclarations[]) -> ObjL1_1, ClVarL, Env, ObjId, insts[constructorCall1(TVClName, ArgL, ObjId)], runnable() ; ConstructorCallWithoutArgument: --BSC: Constructor Processings -- --RC: Retrieves the constructor closure (super() was added at the top of --RC: the constructor instruction list). -- --CS: ClassName1() getConstructorClosure( ObjL, ClVarL, OThId |- TVClName, ObjId, vals[] -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, _, _ |- constructorCall1(TVClName, arguments[], ObjId) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; APIConstructorCallWithoutArgument: --RC: Retrieves the API constructor closure (super() was added at the top --RC: of the constructor instruction list). -- --CS: Thread() APIMethodOrConstructorCall( ObjL1, ClVarL1, OThId, ObjId |- TVClName, vals[] -> ObjL1_1, ClVarL1_1, insts[Clr], runnable() ) -------------------------------- ObjL1, ClVarL1, Env, OThId, _, _ |- constructorCall1(TVClName, arguments[], ObjId) -> ObjL1_1, ClVarL1_1, Env, empty(), insts[Clr], runnable() ; ConstructorCallWithArguments: --RC: Before retrieving the constructor closure, the arguments need to be --RC: evaluated. Makes an evaluation step for the first argument. -- --CS: ClassName1(locVar2, 2+6, Obj1.Attr1) evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode |- ArgL1 -> ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & appendtree( InstL1, insts[constructorCall2(ClName, ArgL1_1, TVObjRef)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode |- constructorCall1(ClName, ArgL1, TVObjRef) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; provided diff( ArgL1, arguments[] ); ConstructorCallWithEvaluatedArguments: --RC: The constructor arguments are all evaluated. The corresponding --RC: closure is retrieved and added to the instruction list. -- --CS: ClassName1(25, 8, #4) evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId1, Mode |- ArgL => ObjL, ClVarL, Env, ArgL, insts[] ) & convertCompArgumentsToValues( ArgL -> ValL ) & getConstructorClosure( ObjL, ClVarL, OThId |- ClName, ObjId2, ValL -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId1, Mode |- constructorCall2(ClName, ArgL, ObjId2) -> ObjL, ClVarL, Env, ObjId2, insts[Clr], runnable() ; ConstructorCallWithArguments_ArgumentsEvaluation: --RC: Evaluates the constructor arguments (resolves for example 2+6). --RC: The aim is to obtain a list of simple values. -- --CS: ClassName1(25, 2+6, Obj1.Attr1) evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode |- ArgL1 => ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[constructorCall2(ClName, ArgL1_1, ObjId2)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode |- constructorCall2(ClName, ArgL1, ObjId2) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; APIConstructorCallWithEvaluatedArguments: --RC: The API constructor arguments are all evaluated. The corresponding --RC: closure is retrieved and added to the instruction list. -- --CS: Thread("MyThread") -- --ESC: Constructor processings APIMethodOrConstructorCall( ObjL1, ClVarL1, OThId, ObjId |- TVIdent, ArgL -> ObjL1_1, ClVarL1_1, insts[Clr], runnable() ) -------------------------------- ObjL1, ClVarL1, Env, OThId, _, _ |- constructorCall2(TVIdent, ArgL, ObjId) -> ObjL1_1, ClVarL1_1, Env, ObjId, insts[Clr], runnable() ; provided diff( ArgL, arguments[] ); ConvertNewArray_DefaultValues: --RC: Creates an array when some the size(s) of some of the dimensions --RC: are given. Note that Java does not allow an array initializer --RC: in this case. convertDimsToSemArgs( NonEmptyDims -> Sizes ) & appendtree( NonEmptyDims, EmptyDims, Dims ) & computeArrayType( ElementType, Dims -> ArrayType ) & evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Sizes => ObjL_1, ClVarL_1, Env_1, Sizes_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- newArray(ElementType, NonEmptyDims, EmptyDims, arrayInitializer[]) -> ObjL_1, ClVarL_1, Env_1, semNewArray(ArrayType, Sizes_1), InstL, runnable() ; provided diff( NonEmptyDims, dims[] ); ConvertNewArray_ArrayInitializer: --RC: Creates an array when an array initializer is given. Note that --RC: Java does not allow any dimension sizes to be given in this case. computeArrayType( ElementType, Dims -> ArrayType ) & convertArrayInitializerToSemArgument( ArrayType, ArrayInit -> Expr ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- newArray(ElementType, dims[], Dims, ArrayInit) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; CreateNewArray_EvaluateSizes: evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Sizes => ObjL_1, ClVarL_1, Env_1, Sizes_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewArray(ArrayType, Sizes) -> ObjL_1, ClVarL_1, Env_1, semNewArray(ArrayType, Sizes_1), InstL, runnable() ; provided not_eq( Sizes, vals[_] ) & allAreValues( Sizes -> false() ); CreateNewArray_SizesEvaluated: convertCompArgumentsToValues( Sizes -> Sizes_1 ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewArray(ArrayType, Sizes_1) -> ObjL_1, ClVarL_1, Env_1, Expr, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewArray(ArrayType, Sizes) -> ObjL_1, ClVarL_1, Env_1, Expr, InstL, ThStatus ; provided not_eq( Sizes, vals[_] ) & allAreValues( Sizes -> true() ); -- !!! Should check for negative sizes somehow and throw an exception in that -- !!! case. Or is it good enough to do let arraySupport check for it? CreateNewArray_OneDimensional: newArray( ArrayType, n, OThId |- ObjL -> ObjL_1, ArrayId, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewArray(ArrayType, vals[integer n]) -> ObjL_1, ClVarL, Env, ArrayId, InstL, runnable() ; CreateNewArray_MultiDimensional: makeNewArrayExprList( n, ArrayType, Sizes -> Exprs ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewInitializedArray(arrayof(ArrayType), Exprs) -> ObjL_1, ClVarL_1, Env_1, Expr, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewArray(arrayof(ArrayType), vals[integer n.Sizes]) -> ObjL_1, ClVarL_1, Env_1, Expr, InstL, ThStatus ; provided not_eq( Sizes, vals[] ); CreateNewInitializedArray_EvaluateElements: evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId, Mode |- ArrayElems => ObjL_1, ClVarL_1, Env_1, ArrayElems_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewInitializedArray(ArrayType, ArrayElems) -> ObjL_1, ClVarL_1, Env_1, semNewInitializedArray(ArrayType, ArrayElems_1), InstL, runnable() ; provided allAreValues( ArrayElems -> false() ); CreateNewInitializedArray_Creation: convertCompArgumentsToValues( ArrayElems -> ArrayElems_1 ) & newArrayWithValues( ArrayType, ArrayElems_1 |- ObjL -> ObjL_1, ArrayId ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semNewInitializedArray(ArrayType, ArrayElems) -> ObjL_1, ClVarL, Env, ArrayId, insts[], runnable() ; provided allAreValues( ArrayElems -> true() ); ConvertPrefixIncr: --RC: Translates e.g. ++i into i+=1. evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- binaryAssign(Expr, plusAssignment(), integer 1) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- prefix(incr(), Expr) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ; ConvertPrefixDecr: --RC: Translates e.g. --i into i-=1. evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- binaryAssign(Expr, minusAssignment(), integer 1) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- prefix(decr(), Expr) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ; ConvertPostfixIncr: --RC: Translates e.g. i++ into (i+=1)-1. evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- binary(binaryAssign(Expr, plusAssignment(), integer 1), minus(), integer 1) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- postfix(Expr, incr()) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ; ConvertPostfixDecr: --RC: Translates e.g. i-- into (i-=1)+1. evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- binary(binaryAssign(Expr, minusAssignment(), integer 1), plus(), integer 1) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- postfix(Expr, decr()) -> ObjL_1, ClVarL_1, Env_1, Expr1, InstL, ThStatus ; ConvertAssignIntoAssignComp1: --BSC: Assignment -- --RC: Convert an assign into a assign_comp before starting the --RC: assignment. -- --CS: Ident = Expression2; evaluateExpression( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semAssign(empty(), TVIdent, AOp, Expr1) -> ObjL1_1, ClVarL1_1, Env1_1, Expr2, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- binaryAssign(TVIdent, AOp, Expr1) -> ObjL1_1, ClVarL1_1, Env1_1, Expr2, InstL, ThStatus ; ConvertAssignIntoAssignComp2: --RC: Convert an assign into a assign_comp before starting theö --RC: assignment. -- --CS: Expression1 = Expression2; evaluateExpression( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semAssign(Expr2, Ident, AOp, Expr1) -> ObjL1_1, ClVarL1_1, Env1_1, Expr3, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- binaryAssign(access(Expr2, Ident), AOp, Expr1) -> ObjL1_1, ClVarL1_1, Env1_1, Expr3, InstL, ThStatus ; ClassVariableAssignment_LastStep: --RC: The value is assigned to the class variable. -- --CS: ClassName2.ClVarName3 = 25; setClassVariable( TVClName, ClVarName, TVValue |- ClVarL1 -> ClVarL1_1 ) -------------------------------- ObjL, ClVarL1, Env, _, _, _ |- semAssign(TVClName, ClVarName, assignment(), TVValue) -> ObjL, ClVarL1_1, Env, TVValue, insts[], runnable() ; provided isAClass( TVClName -> true() ); ClassVariableAssignment_HandleCompoundAssignment: --RC: Translates e.g. A.b += 25 to A.b = A.b + 25. Safe since all parts --RC: have been evaluated. --CS: ClassName2.ClVarName3 += 25; getOpFromCompundAssignOp( AOp -> Op ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVClName, ClVarName, assignment(), binary(semAccess(TVClName, ClVarName), Op, TVValue)) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVClName, ClVarName, AOp, TVValue) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; provided isAClass( TVClName -> true() ) & isCompoundAssignOp( AOp -> true() ); ClassVariableAssignment_RightHandMemberEvaluation: --RC: Before being assigned to the class variable, the right member needs --RC: to be evaluated. -- --CS: ClassName1.ClVarName2 = Obj.attr5; isAClass( TVClName -> true() ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVClName, ClVarName, AOp, Expr) -> ObjL_1, ClVarL_1, Env_1, semAssign(TVClName, ClVarName, AOp, Expr_1), InstL, ThStatus ; ComplexAssignValueToASimpleVariable: --RC: Assigns a value to a variable (parameter or local variable). -- --CS: var1 = 10; assign( ObjL1, ClVarL1, Env1, ObjId |- Ident, TVValue -> ObjL1_1, ClVarL1_1, Env1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, _, ObjId, _ |- semAssign(empty(), Ident, assignment(), TVValue) -> ObjL1_1, ClVarL1_1, Env1_1, TVValue, insts[], runnable() ; ComplexAssignValueToASimpleVariable_HandleCompoundAssignment: --RC: Translates e.g. a += 25 to a = a + 25. Safe since all parts --RC: have been evaluated. -- --CS: var1 += 10; getOpFromCompundAssignOp( AOp -> Op ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(empty(), Ident, assignment(), binary(Ident, Op, TVValue)) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(empty(), Ident, AOp, TVValue) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; provided isCompoundAssignOp( AOp -> true() ); ComplexAssignExpressionToASimpleVariable: --RC: Evaluates the right member of the assignment before assigning the --RC: variable. -- --CS: var1 = 25 + var2; evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(empty(), Ident, AOp, Expr) -> ObjL_1, ClVarL_1, Env_1, semAssign(empty(), Ident, AOp, Expr_1), InstL, ThStatus ; ComplexAssignValueToAnAttributeOrAStaticVariable: --RC: Assigns a value to an attribute or a static variable. -- --CS: #4.Attr = 25; setAttributeOrStaticVariable( ObjL1, ClVarL1, TVObjId |- Ident, TVValue -> ObjL1_1, ClVarL1_1 ) -------------------------------- ObjL1, ClVarL1, Env, _, _, _ |- semAssign(TVObjId, Ident, assignment(), TVValue) -> ObjL1_1, ClVarL1_1, Env, TVValue, insts[], runnable() ; ComplexAssignValueToAnAttributeOrAStaticVariable_HandleCompoundAssignment: --RC: Translates e.g. #1.a += 25 to #1.a = #1.a + 25. Safe since all --RC: parts have been evaluated. -- --CS: #4.Attr = 25; getOpFromCompundAssignOp( AOp -> Op ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVObjId, Ident, assignment(), binary(semAccess(TVObjId, Ident), Op, TVValue)) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVObjId, Ident, AOp, TVValue) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; provided isCompoundAssignOp( AOp -> true() ); ComplexAssignExpressionViaNull: --RC: Attempt to assign via a null reference to an object. --RC: Throw an exception. -- --CS: null().Attr = Var1 * Var2; createExceptionObject( ObjL1_1, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL1_2, InstL ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode |- semAssign(null(), _, _, _) -> ObjL1_2, ClVarL1_1, Env1_1, empty(), InstL, runnable() ; ComplexAssignExpressionToAnAttributeOrAStaticVariable: --RC: Evaluates the right member of the assignment before assigning the --RC: attribute or the class variable. -- --CS: #4.Attr = 5 * var3; evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(TVObjId, Ident, AOp, Expr) -> ObjL_1, ClVarL_1, Env_1, semAssign(TVObjId, Ident, AOp, Expr_1), InstL, ThStatus ; ComplexAssignement_LeftHandMemberEvaluation: --RC: Evaluates the left member of the assignment before the evaluation --RC: of the right member and the assignment. -- --CS: ObjName1.ObjAttr1.ObjAttr3 = 25 * Var5 + Var1; -- --ESC: Assignment evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr1 -> ObjL_1, ClVarL_1, Env_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semAssign(Expr1, Ident, AOp, Expr2) -> ObjL_1, ClVarL_1, Env_1, semAssign(Expr1_1, Ident, AOp, Expr2), InstL, ThStatus ; ConvertArrayAssignmentToSemArrayAssign: --RC: Convert an assignment to an array element into a semArrayAssign operator. -- --CS: Expression1[Expression2] = Expression3. evaluateExpression( ObjL, ClVarL, Env, OthId, ObjId, Mode |- semArrayAssign(Expr1, Expr2, AOp, Expr3) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OthId, ObjId, Mode |- binaryAssign(arrayAccess(Expr1, Expr2), AOp, Expr3) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; ComplexArrayAssignment_ArrayEvaluation: --RC: The array part of the assignment access is not yet a reference (null or object --RC: id). Evaluate it one more step. -- --CS: Expression1[Expression2] = Expression3 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr1 -> ObjL_1, ClVarL_1, Env_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAssign(Expr1, Expr2, AOp, Expr3) -> ObjL_1, ClVarL_1, Env_1, semArrayAssign(Expr1_1, Expr2, AOp, Expr3), InstL, ThStatus ; provided not_eq( Expr1, objectId(_, _) ) & not_eq( Expr1, null() ); ComplexArrayAssignment_IndexEvaluation: --RC: The index part of the access is not yet an integer. Evaluate it one more step. -- --CS: #4[Expression2] = Expression3 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr2 -> ObjL_1, ClVarL_1, Env_1, Expr2_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAssign(TVObjRef, Expr2, AOp, Expr3) -> ObjL_1, ClVarL_1, Env_1, semArrayAssign(TVObjRef, Expr2_1, AOp, Expr3), InstL, ThStatus ; provided not_eq( Expr2, integer _ ); ComplexArrayAssignment_ValueEvaluation: --RC: The value has not yet been fully evaluated. Evaluate it one more step. -- --CS: #4[7] = Expression3 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr3 -> ObjL_1, ClVarL_1, Env_1, Expr3_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAssign(TVObjRef, integer i, AOp, Expr3) -> ObjL_1, ClVarL_1, Env_1, semArrayAssign(TVObjRef, integer i, AOp, Expr3_1), InstL, ThStatus ; provided isValue( Expr3 -> false() ); ComplexArrayAssignment_NullPointer: --RC: The array reference is null. Throw an exception. (Note that this is not --RC: checked until the index and the value has been fully evaluated.) --RC: NOTE! This rule will not catch uninitialized local variables (value = empty()) --RC: since this is a STATIC error. -- --CS: null()[7] = 42 createExceptionObject( ObjL1, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- semArrayAssign(null(), integer _, _, TVValue) -> ObjL1_1, ClVarL, Env, empty(), InstL, runnable() ; ComplexArrayAssignment_SetElement: --RC: Sets the element at the indicated index to value. An exception is thrown --RC: if the index is out of bounds, or if the element type is incompatible with --RC: the dynamic type of the array. -- --CS: #1[7] = 10; setArrayElement( TVObjId, i, TVValue, OThId |- ObjL -> ObjL_1, InstL ) -------------------------------- ObjL, ClVarL, Env, OThId, _, _ |- semArrayAssign(TVObjId, integer i, assignment(), TVValue) -> ObjL_1, ClVarL, Env, TVValue, InstL, runnable() ; ComplexArrayAssignment_HandleCompoundAssignment: --RC: Translates e.g. #1[7] += 25 to #1[7] = #1[7] + 25. Safe since all --RC: parts have been evaluated. -- --CS: #1[7] = 10; getOpFromCompundAssignOp( AOp -> Op ) & evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAssign(TVObjId, integer i, assignment(), binary(semArrayAccess(TVObjId, integer i), Op, TVValue)) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- semArrayAssign(TVObjId, integer i, AOp, TVValue) -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ; provided isCompoundAssignOp( AOp -> true() ); ExceptionThrownDuringABinaryOperationEvaluation: --BSC: Binary Operator Expression -- --RC: The binary operator evaluation has thrown an exception (for --RC: example at the time of a division by zero). -- --CS: 25 / 0; evaluateBinaryOperation( |- TVValue1, TVValue2, BinOp -> except(ClName, null(), ExceptText) ) & createExceptionObject( ObjL1, OThId |- ClName, ExceptText -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- binary(TVValue1, BinOp, TVValue2) -> ObjL1_1, ClVarL, Env, empty(), InstL, runnable() ; BinaryOperationBetweenTwoValues: --RC: Evaluates the binary operation between the two values. -- --CS: 25 + 4 or 100 < 200 evaluateBinaryOperation( |- TVValue1, TVValue2, BinOp -> TVValue3 ) -------------------------------- ObjL1, ClVarL1, Env1, _, _, _ |- binary(TVValue1, BinOp, TVValue2) -> ObjL1, ClVarL1, Env1, TVValue3, insts[], runnable() ; BinaryOperation_LogicalOrWithTrueAsLeftValue: --RC: The left member of the binary operation is already a value. -- --CS: true() || ... ObjL, ClVarL, Env, _, _, _ |- binary(true(), lor(), _) -> ObjL, ClVarL, Env, true(), insts[], runnable() ; BinaryOperation_LogicalAndWithFalseAsLeftValue: --RC: The left member of the binary operation is already a value. The --RC: right member is still an expression which needs to be evaluated --RC: before the evaluation of the binary operation. -- --CS: false() && ..... ObjL, ClVarL, Env, _, _, _ |- binary(false(), land(), _) -> ObjL, ClVarL, Env, false(), insts[], runnable() ; BinaryOperation_RightHandMemberEvaluation: --RC: The left member of the binary operation is already a value. The --RC: right member is still an expression which needs to be evaluated --RC: before the evaluation of the binary operation. -- --CS: 25 + Obj1.Attr3 evaluateExpression( ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- Expr1 -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- binary(TVValue, BinOp, Expr1) -> ObjL1_1, ClVarL1_1, Env1_1, binary(TVValue, BinOp, Expr1_1), InstL, ThStatus ; BinaryOperation_LeftHandMemberEvaluation: --RC: The left member of the binary operation is still an expression which --RC: needs to be evaluated before the evaluation of the right member. -- --CS: Obj2.Attr4 + Obj1.Attr3 -- --ESC: Binary Operator Expression evaluateExpression( ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- Expr1 -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL1, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- binary(Expr1, BinOp, Expr2) -> ObjL1_1, ClVarL1_1, Env1_1, binary(Expr1_1, BinOp, Expr2), InstL1, ThStatus ; UnaryOperation_ArgumentEvaluation: --RC: The argument is not yet a value. Evaluate it one more step. -- --CS: -(7 + 3) or !(true && false) evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr -> ObjL_1, ClVarL_1, Env_1, Expr_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- unary(UnOp, Expr) -> ObjL_1, ClVarL_1, Env_1, unary(UnOp, Expr_1), InstL, ThStatus ; provided isValue( Expr -> false() ); UnaryOperation_ApplyOperator: --RC: Applies an unary to a value. --RC: Unary operators don't throw exceptions. -- --CS: -7 or !true evaluateUnaryOperation( |- TVValue, UnOp -> Result ) -------------------------------- ObjL, ClVarL, Env, _, _, _ |- unary(UnOp, TVValue) -> ObjL, ClVarL, Env, Result, insts[], runnable() ; CondExpr_PrediceteEvaluation: --RC: The predicate is not yet a value. Evaluate it one more step. -- --CS: p ? e1 : e2 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Pred -> ObjL_1, ClVarL_1, Env_1, Pred_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- cond(Pred, Expr1, Expr2) -> ObjL_1, ClVarL_1, Env_1, cond(Pred_1, Expr1, Expr2), InstL, ThStatus ; provided isValue( Pred -> false() ); CondExpr_PredIsTrue: --RC: Predicate evaluated to true. Select left expression for further --RC: evaluation. -- --CS: true ? e1 : e2 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr1 -> ObjL_1, ClVarL_1, Env_1, Expr1_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- cond(true(), Expr1, _) -> ObjL_1, ClVarL_1, Env_1, Expr1_1, InstL, ThStatus ; CondExpr_PredIsFalse: --RC: Predicate evaluated to true. Select left expression for further --RC: evaluation. -- --CS: false ? e1 : e2 evaluateExpression( ObjL, ClVarL, Env, OThId, ObjId, Mode |- Expr2 -> ObjL_1, ClVarL_1, Env_1, Expr2_1, InstL, ThStatus ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- cond(false(), _, Expr2) -> ObjL_1, ClVarL_1, Env_1, Expr2_1, InstL, ThStatus ; ThisWithoutArgument: --BSC: This() Call Expression -- --RC: This expression is only used in a constructor declaraction to invoke --RC: the class constructor without argument. -- --CS: this(); -- --PC: Firstly the class name and the corresponding class declaration are --PC: retrieved. Finally, the obtained closure is added to the current --PC: thread instruction list. getThreadCurrentMethod( OThId |- ObjL -> ClName ) & getConstructorClosure( ObjL, ClVarL, OThId |- ClName, ObjId, vals[] -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, _ |- thisInvocation(arguments[]) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; ThisWithArguments_FirstArgumentsEvaluation: --RC: This expression is only used in a constructor declaration to invoke --RC: another constructor that also belongs to this same class. The --RC: arguments used for this constructor need firstly to be evaluated. -- --CS: this(Obj2.Attr5, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL1 -> ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & appendtree( InstL1, insts[thisCall(this(), ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- thisInvocation(ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, ObjId, InstL1_1, runnable() ; provided diff( ArgL1, arguments[] ); ThisWithArguments_ArgumentsEvaluation: --RC: The arguments of the this() call (used in a constructor to invoke an --RC: other constructor of the same class) are evaluated step by step. -- --CS: this(345, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- ArgL1 => ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[thisCall(this(), ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId1, ObjId, Mode |- thisCall(this(), ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, ObjId, InstL1_1, runnable() ; ThisWithArguments_EvaluatedArguments: --RC: All the arguments of the this() call (used in a constructor to --RC: invoke another constructor of the same class) have been evaluated. --RC: So the closure corresponding to this this() call is retrieved and --RC: added to the current thread instruction list. -- --CS: this(345, 57, 959); -- --ESC: This() Call Expression evaluateArgument( ObjL, ClVarL, Env1, OThId, ObjId, Mode |- ArgL => ObjL, ClVarL, Env1, ArgL, insts[] ) & convertCompArgumentsToValues( ArgL -> ValueL ) & getThreadCurrentMethod( OThId |- ObjL -> ClName ) & getConstructorClosure( ObjL, ClVarL, OThId |- ClName, ObjId, ValueL -> Clr ) -------------------------------- ObjL, ClVarL, Env1, OThId, ObjId, Mode |- thisCall(this(), ArgL) -> ObjL, ClVarL, Env1, empty(), insts[Clr], runnable() ; SuperWithoutArgument: --BSC: Super Call Expression -- --RC: This expression is only used in a constructor declaraction to invoke --RC: the super class constructor (direct ancestor of the current class) --RC: without argument. -- --CS: super(); -- --PC: Firstly the current class and its direct ancestor are retrieved. --PC: Finally, the obtained closure is added to the current thread --PC: instruction list. getThreadCurrentMethod( OThId |- ObjL -> ClName1 ) & getDirectAncestor( |- ClName1 -> ClName2 ) & getConstructorClosure( ObjL, ClVarL, OThId |- ClName2, ObjId, vals[] -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, _ |- superInvocation(arguments[]) -> ObjL, ClVarL, Env, OThId, insts[Clr], runnable() ; SuperWithArguments_FirstArgumentsEvaluation: --RC: This expression is only used in a constructor declaration to invoke --RC: its direct ancestor constructor with its arguments. These latters --RC: need firstly to be evaluated. -- --CS: super(Obj2.Attr5, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL1 -> ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & appendtree( InstL1, insts[superCall(super(), ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- superInvocation(ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; provided diff( ArgL1, arguments[] ); SuperWithArguments_ArgumentsEvaluation: --RC: The arguments of the super() call (used in a constructor to invoke --RC: its direct ancestor constructor) are evaluated step by step. -- --CS: super(345, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL1 => ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[superCall(super(), ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- superCall(super(), ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; SuperWithArguments_EvaluatedArguments: --RC: All the arguments of the super() call (used in a constructor to --RC: invoke its direct ancestor constructor have been evaluated. --RC: So the closure corresponding to this super() call is retrieved and --RC: added to the current thread instruction list. -- --CS: super(345, 57, 959); -- --ESC: Super() Call Expression evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId, Mode |- TVArgL => ObjL, ClVarL, Env, TVArgL, insts[] ) & convertCompArgumentsToValues( TVArgL -> ValueL ) & getThreadCurrentMethod( OThId |- ObjL -> ClName1 ) & getDirectAncestor( |- ClName1 -> ClName2 ) & getConstructorClosure( ObjL, ClVarL, OThId |- ClName2, ObjId, ValueL -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- superCall(super(), TVArgL) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; MethodCallWithoutReference_ReferenceRetrieval: --BSC: Method call expression -- --RC: This method is called without reference. That means that the method --RC: is applied on the current object. Moreover, a special variable --RC: called 7RETURN is added to the local variable list in order to handle --RC: the value returned by this method. -- --CS: getVal2(); addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL, ClVarL, env(ParamL, LocVarL1), _, ObjId, identifier "none" |- call(TVMethName, ArgL) -> ObjL, ClVarL, env(ParamL, LocVarL1_1), identifier "7RETURN", insts[methodCall1(identifier "virtual", ObjId, TVMethName, ArgL)], runnable() ; MethodCallWithoutReferenceInAStaticMethod: --RC: This method is called without reference in a static method. So that --RC: is a static method. Moreover, a special variable called 7RETURN --RC: is added to the local variable list in order to handle the value --RC: returned by this method. -- --CS: getInstancesNumber(); addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL, ClVarL, env(ParamL, LocVarL1), _, _, ClName |- call(TVMethName, ArgL) -> ObjL, ClVarL, env(ParamL, LocVarL1_1), identifier "7RETURN", insts[staticMethodCall1(ClName, TVMethName, ArgL)], runnable() ; provided diff( ClName, identifier "none" ); MethodCallWithAnEmptyObjectReference: --RC: This method is called with a class name. That means that this method -- --CS: null.currentThread(); createExceptionObject( ObjL1, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- call(access(null(), MethName), ArgL) -> ObjL1_1, ClVarL, Env, empty(), InstL, runnable() ; MethodCallWithAClassName: --RC: This method is called with a class name. That means that this method --RC: is static. Moreover, a special variable called 7RETURN is added to --RC: the local variable list in order to handle the value returned by --RC: this static method. -- --CS: Thread.currentThread(); isAClass( TVClName -> true() ) & addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL, ClVarL, env(ParamL, LocVarL1), _, _, _ |- call(access(TVClName, MethName), ArgL) -> ObjL, ClVarL, env(ParamL, LocVarL1_1), identifier "7RETURN", insts[staticMethodCall1(TVClName, MethName, ArgL)], runnable() ; MethodCallOnAnObject: --RC: This method is called on an object (so this method is non static). --RC: Moreover, a special variable called 7RETURN is added to the local --RC: variable list in order to handle the value returned by this method. -- --CS: myObject.setAttrValue(var2 - var1); getVariableValue( ObjL, ClVarL, env(ParamL, LocVarL1), ObjId |- TVObjName -> TVObjRef ) & addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL, ClVarL, env(ParamL, LocVarL1), _, ObjId, _ |- call(access(TVObjName, MethName), ArgL) -> ObjL, ClVarL, env(ParamL, LocVarL1_1), identifier "7RETURN", insts[methodCall1(identifier "virtual", TVObjRef, MethName, ArgL)], runnable() ; MethodCall_TargetEvaluationWithAnotherMethodCall: --RC: Before executing the given method, the target object represented --RC: here by a method call must be retrieved. Therefore this method call --RC: is evaluated. Moreover, a special variable called 7RETURN is added to --RC: the local variable list in order to handle the value returned by --RC: this method. -- --CS: myObject.bar().setAttrValue(var2 - var1); evaluateExpression( ObjL1, ClVarL1, Env, OThId, ObjId, Mode |- call(Expr1, ArgL1) -> ObjL1_1, ClVarL1_1, env(ParamL1, LocVarL1), _, InstL1, ThStatus ) & diff( InstL1, insts[] ) & appendtree( InstL1, insts[call(access(identifier "7RETURN", MethName), ArgL2)], InstL1_1 ) & addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL1, ClVarL1, Env, OThId, ObjId, Mode |- call(access(call(Expr1, ArgL1), MethName), ArgL2) -> ObjL1_1, ClVarL1_1, env(ParamL1, LocVarL1_1), identifier "7RETURN", InstL1_1, ThStatus ; MethodCall_TargetEvaluationWithNoOtherMethodCall: --RC: Before executing the given method, the target object represented --RC: here by an expression must be retrieved. Therefore this expression --RC: is evaluated. Moreover, a special variable called 7RETURN is added to --RC: the local variable list in order to handle the value returned by --RC: this method. -- --CS: myObject.Attr1.setAttrValue(var2 - var1); not_eq( Expr1, call(_, _) ) & evaluateExpression( ObjL1, ClVarL1, Env, OThId, ObjId, Mode |- Expr1 -> ObjL1_1, ClVarL1_1, env(ParamL1, LocVarL1), Expr1_1, insts[], ThStatus ) & appendtree( insts[semAssign(empty(), identifier "7RETURN", assignment(), Expr1_1)], insts[call(access(identifier "7RETURN", MethName), ArgL)], InstL2_1 ) & addReturnVariableInLocalVariableList( LocVarL1 -> LocVarL1_1 ) -------------------------------- ObjL1, ClVarL1, Env, OThId, ObjId, Mode |- call(access(Expr1, MethName), ArgL) -> ObjL1_1, ClVarL1_1, env(ParamL1, LocVarL1_1), identifier "7RETURN", InstL2_1, ThStatus ; NonStaticMethodCalledOnANonCreatedObject: --RC: The method is called on a non created object. So an exception is --RC: thrown. -- --CS: void().getValue(); createExceptionObject( ObjL1, OThId |- identifier "NullPointerException", exceptText "Use of a pointer with a null value." -> _, ObjL1_1, InstL ) -------------------------------- ObjL1, ClVarL, Env, OThId, _, _ |- methodCall1(_, null(), _, _) -> ObjL1_1, ClVarL, Env, empty(), InstL, runnable() ; NonStaticMethodCallAPI_WithoutArgument: --RC: The given method is a defined javacard API. This API does not have --RC: argument. -- --CS: myThread.start(); APIMethodOrConstructorCall( ObjL1, ClVarL1, OThId, TVObjId |- MethName, vals[] -> ObjL1_1, ClVarL1_1, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env, OThId, _, _ |- methodCall1(_, TVObjId, MethName, arguments[]) -> ObjL1_1, ClVarL1_1, Env, empty(), InstL, ThStatus ; NonStaticMethodCallWithoutArgument_ClosureAddition: --RC: Gets the closure corresponding to the given method call (this call --RC: does not have any argument to evaluate) and adds it to the current --RC: thread instruction list. (in this case, the object, on which the --RC: given method has been called, has already been created). -- --CS: #5.getValue(); getMethodClosure( ObjL |- MethName, TVObjId, vals[] -> Clr ) -------------------------------- ObjL, ClVarL, Env, _, _, _ |- methodCall1(_, TVObjId, MethName, arguments[]) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; NonStaticMethodCallWithArguments_FirstArgumentEvaluation: --RC: One evaluation step of the first argument is made. -- --CS: #4.myMethod(Obj2.Attr2, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode1 |- ArgL1 -> ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[methodCall2(Mode2, TVObjId, MethName, ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode1 |- methodCall1(Mode2, TVObjId, MethName, ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; provided diff( ArgL1, arguments[] ); NonStaticMethodCallWithEvaluatedArguments_ClosureAddition: --RC: All the arguments of the method call have been evaluated. So the --RC: method declaration and the corresponding closure are retrieved. -- --CS: #4.myMethod(345, 57, false); evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId1, Mode |- ArgL => ObjL, ClVarL, Env, ArgL, insts[] ) & convertCompArgumentsToValues( ArgL -> ValueL ) & getMethodClosure( ObjL |- MethName, ObjId2, ValueL -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId1, Mode |- methodCall2(_, ObjId2, MethName, ArgL) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; NonStaticMethodCallWithArguments_ArgumentsEvaluation: --RC: The arguments of the method call are evaluated step by step before --RC: the method declaration retrieval. -- --CS: #4.myMethod(#5.Attr2, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode1 |- ArgL1 => ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[methodCall2(Mode2, ObjId2, MethName, ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId1, Mode1 |- methodCall2(Mode2, ObjId2, MethName, ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; NonStaticMethodCallAPI_WithEvaluatedArguments: --RC: The given method is a defined javacard API. This API has arguments --RC: which have been evaluated. -- --CS: #4.wait(45); evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId1, Mode |- ArgL => ObjL, ClVarL, Env, ArgL, insts[] ) & convertCompArgumentsToValues( ArgL -> ValueL ) & APIMethodOrConstructorCall( ObjL1, ClVarL1, OThId, ObjId2 |- MethName, ValueL -> ObjL1_1, ClVarL1_1, InstL, ThStatus ) -------------------------------- ObjL1, ClVarL1, Env, OThId, ObjId1, Mode |- methodCall2(_, ObjId2, MethName, ArgL) -> ObjL1_1, ClVarL1_1, Env, empty(), InstL, ThStatus ; StaticMethodCallWithoutArgument: --RC: The static method call has no argument. So the corresponding closure --RC: is retrieved. -- --CS: MyClass.getInstanceNumber(); getStaticMethodClosure( ObjL, OThId |- MethName, ClName, vals[] -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, _, _ |- staticMethodCall1(ClName, MethName, arguments[]) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; StaticMethodCallWithArguments_FirstArgumentEvaluation: --RC: One evaluation step of the first argument is made. -- --CS: MyClass.myMethod(Obj2.Attr2, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL1 -> ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & appendtree( InstL1, insts[staticMethodCall2(ClName, MethName, ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- staticMethodCall1(ClName, MethName, ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; provided diff( ArgL1, arguments[] ); StaticMethodCallWithArguments_ArgumentsEvaluation: --RC: The arguments of the static method call are evaluated step by step --RC: before the method declaration retrieval. -- --CS: MyClass.myMethod(#5.Attr2, 3+6*9, Obj1.getVal()); evaluateArgument( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL1 => ObjL1_1, ClVarL1_1, Env1_1, ArgL1_1, InstL1 ) & diff( ArgL1, ArgL1_1 ) & appendtree( InstL1, insts[staticMethodCall2(ClName, MethName, ArgL1_1)], InstL1_1 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- staticMethodCall2(ClName, MethName, ArgL1) -> ObjL1_1, ClVarL1_1, Env1_1, empty(), InstL1_1, runnable() ; StaticMethodCallWithEvaluatedArguments_ClosureAddition: --RC: All the arguments of the static method call have been evaluated. So --RC: the static method declaration and the corresponding closure are --RC: retrieved. -- --CS: MyClass.myMethod(345, 57, false); -- --ESC: Method call expression evaluateArgument( ObjL, ClVarL, Env, OThId, ObjId, Mode |- ArgL => ObjL, ClVarL, Env, ArgL, insts[] ) & convertCompArgumentsToValues( ArgL -> ValueL ) & getStaticMethodClosure( ObjL, OThId |- MethName, ClName, ValueL -> Clr ) -------------------------------- ObjL, ClVarL, Env, OThId, ObjId, Mode |- staticMethodCall2(ClName, MethName, ArgL) -> ObjL, ClVarL, Env, empty(), insts[Clr], runnable() ; end evaluateExpression; set addReturnVariableInLocalVariableList is --SC: Adds the 7RETURN variable (used to set the return value of a method --SC: call) to the most recent local variable pair list if it is not present --SC: in this latter list. If it is already present (placed on the top of --SC: this list), nothing is done. -- --JC: Local variables --JC: -> Local variable list with the 7RETURN variable judgement (Locs -> Locs); --iJC: Pair list --iJC: -> Pair list with the 7RETURN pair. judgement (Pairs => Pairs); TakesTheOnlyFirstPairListInTheLocalVariableList: --RC: The 7RETURN variable needs to be added in the most recent local --RC: variable pair list. So only the first pair list is concerned about --RC: this addition. (PairL1 => PairL1_1) -------------------------------- (locs[PairL1.LocVarL] -> locs[PairL1_1.LocVarL]) ; EmptyPairList_7RETURNAddition: (pairs[] => pairs[pair(identifier "7RETURN", empty())]) ; RETURNAlreadyPresent_NoAddition: (pairs[pair(identifier "7RETURN", Value).PairL] => pairs[pair(identifier "7RETURN", Value).PairL]) ; RETURNAbsent_7RETURNAddition: --RC: The first pair is checked to know if it is useful to add the 7RETURN --RC: pair at the top of the local variable first pair list. --RC: (The 7RETURN variable pair can only be the first pair of the list) appendtree( pairs[pair(identifier "7RETURN", empty())], pairs[pair(identifier X, Value).PairL1], PairL1_1 ) -------------------------------- (pairs[pair(identifier X, Value).PairL1] => PairL1_1) ; provided diff( identifier X, identifier "7RETURN" ); end addReturnVariableInLocalVariableList; set getConstructorClosure is --SC: Retrieves the instruction list and the environment corresponding to the --SC: constructor declaraction. If there is neither a super() nor a this() --SC: explicit invocation on top of the instruction list, a super() --SC: invocation is added on its top. -- --JC: Objects, Class variables, Current executing thread reference --JC: |- Constructor name (also the class name), --JC: Created object reference, Constructor parameter values --JC: -> Closure corresponding to the given constructor call (the new created --JC: object reference, constructor name, environment for the execution, --JC: instruction list). judgement Objects, ClassVariablesL, ObjectId |- Identifier, ObjectId, Vals -> Clr; --iJC: Arguments values, Current object reference --iJC: |- Constructor declaration --iJC: -> Closure judgement Vals, ObjectId |- java -> Clr; EntryRule_NonAPIConstructorCall: getFieldDeclaration( ObjL, ClName, ValueL, true() |- ClName -> ConstDec, _, true() ) & ValueL, ObjId |- ConstDec -> Clr -------------------------------- ObjL, _, _ |- ClName, ObjId, ValueL -> Clr ; ExplicitThisOrSuperInvocationInTheConstructorDeclaration: --RC: Retrieves the instruction list and the environment corresponding to --RC: the constructor declaraction (in this case, there is already a --RC: super() or this() explicit invocation). getInstructionsAndLocalVariables( insts[], locs[pairs[]] |- BlockElemL => InstL, LocVarL ) & makeBindedParamList( ValueL |- ParamL -> BindParamL ) -------------------------------- ValueL, ObjId |- constructorDeclaration(_, constructor(ClName, ParamL), _, constructorBody(SuperOrThis, BlockElemL)) -> clr(ObjId, identifier "none", ClName, env(BindParamL, LocVarL), insts[SuperOrThis.InstL]) ; NonExplicitThisOrSuperInvocationInTheConstructorDeclaration: --RC: As there is no this() or super() explicit invocation on the top of --RC: the constructor declaration instruction list, a super() invocation --RC: must be added to the corresponding closure instruction list. getInstructionsAndLocalVariables( insts[], locs[pairs[]] |- Block => InstL, LocVarL ) & makeBindedParamList( ValueL |- ParamL -> BindParamL ) -------------------------------- ValueL, ObjId |- constructorDeclaration(_, constructor(ClName, ParamL), _, Block) -> clr(ObjId, identifier "none", ClName, env(BindParamL, LocVarL), insts[superInvocation(arguments[]).InstL]) ; APIConstructorCallWithoutArgument: APIMethodOrConstructorCall( ObjL1, ClVarL1, OThId, ObjId |- ClName, ValueL -> _, _, insts[Clr], _ ) -------------------------------- ObjL1, ClVarL1, OThId |- ClName, ObjId, ValueL -> Clr ; end getConstructorClosure; set getMethodClosure is --SC: Gets the closure corresponding to a method call. -- --JC: Objects, Class variables --JC: |- Method name for which the closure is wanted, Object (on which the --JC: method is called) reference, method parameter values --JC: -> Closure for the given method call. judgement Objects |- Identifier, Ref, Vals -> Clr; getObjectType( ObjId |- ObjL -> ClName ) & getFieldDeclaration( ObjL, ClName, ValueL, false() |- MethName -> MethDec, _, true() ) & makeClosure( ClName, ValueL, ObjId |- MethDec -> Clr ) -------------------------------- ObjL |- MethName, ObjId, ValueL -> Clr ; end getMethodClosure; set getStaticMethodClosure is --SC: Gets the closure corresponding to a static method call. -- --JC: Objects, Class variables, current executing thread reference --JC: |- Static method name for which the closure is wanted, Class name that --JC: ccntains the given static method, Method parameter values --JC: -> Closure for the given static method call. judgement Objects, ObjectId |- Identifier, Identifier, Vals -> Clr; getFieldDeclaration( ObjL, ClName, ValueL, false() |- MethName -> MethDec, _, true() ) & makeClosure( ClName, ValueL, OThId |- MethDec -> Clr ) -------------------------------- ObjL, OThId |- MethName, ClName, ValueL -> Clr ; end getStaticMethodClosure; set assign is --SC: Assign a value to an identifier. Firstly the variable is sought into --SC: the parameter list, then into the local variable list and finally into --SC: the object attributes or in the class variable list associated with the --SC: object type. -- --JC: Objects, Class variables, Environment, Current object reference --JC: |- Identifier of the sought variable, Value to assign --JC: -> Updated object list, Updated class variables, Updated environment; --JC: (only one of these three elements is modified) judgement Objects, ClassVariablesL, Env, ObjectId |- Identifier, Val -> Objects, ClassVariablesL, Env; ParameterAssignment: setVariableIntoAPairList( Ident, Value |- ParamL1 -> ParamL1_1, true() ) -------------------------------- ObjL, ClVarL, env(ParamL1, LocVarL), _ |- Ident, Value -> ObjL, ClVarL, env(ParamL1_1, LocVarL) ; LocalVariableAssignment: setVariableIntoAPairList( Ident, Value |- ParamL -> _, false() ) & setLocalVariable( Ident, Value |- LocVarL1 -> LocVarL1_1, true() ) -------------------------------- ObjL, ClVarL, env(ParamL, LocVarL1), _ |- Ident, Value -> ObjL, ClVarL, env(ParamL, LocVarL1_1) ; AttributeAssignment: setVariableIntoAPairList( Ident, Value |- ParamL -> _, false() ) & setLocalVariable( Ident, Value |- LocVarL -> _, false() ) & setAttribute( Ident, Value, ObjId |- ObjL1 -> ObjL1_1, true() ) -------------------------------- ObjL1, ClVarL, env(ParamL, LocVarL), ObjId |- Ident, Value -> ObjL1_1, ClVarL, env(ParamL, LocVarL) ; ClassVariableAssignment: setVariableIntoAPairList( Ident, Value |- ParamL -> _, false() ) & setLocalVariable( Ident, Value |- LocVarL -> _, false() ) & setAttribute( Ident, Value, ObjId |- ObjL -> _, false() ) & setClassVariable( ObjL, Ident, Value, ObjId |- ClVarL1 => ClVarL1_1 ) -------------------------------- ObjL, ClVarL1, env(ParamL, LocVarL), ObjId |- Ident, Value -> ObjL, ClVarL1_1, env(ParamL, LocVarL) ; end assign; set setVariableIntoAPairList is --SC: Assigns a value to a variable into a pair list. -- --JC: Sought variable, Value to assign to this latter variable --JC: |- Pair list --JC: -> Updated pair list, true or false depending on the result of the --JC: search of the variable into the list; judgement Identifier, Val |- Pairs -> Pairs, Bool; VariableFound_Assignment: Ident, Value |- pairs[pair(Ident, _).PairL] -> pairs[pair(Ident, Value).PairL], true() ; EmptyList_NoAssignment: _, _ |- pairs[] -> pairs[], false() ; RecursiveSearchIntoTheList: Ident1, Value1 |- PairL1 -> PairL1_1, TF -------------------------------- Ident1, Value1 |- pairs[pair(Ident2, Value2).PairL1] -> pairs[pair(Ident2, Value2).PairL1_1], TF ; provided diff( Ident2, Ident1 ); end setVariableIntoAPairList; set setLocalVariable is --SC: Assigns a value to a variable into the local variable list. -- --JC: Sought local variable, Value to assign to this latter variable --JC: |- Local variable list --JC: -> Updated local variable list, true or false depending on the result --JC: of the search of the variable into the list judgement Identifier, Val |- Locs -> Locs, Bool; EmptyList_NoAssignment: _, _ |- locs[] -> locs[], false() ; VariableFoundIntoTheFirstPairList_Assignment: setVariableIntoAPairList( Ident, Value |- PairL1 -> PairL1_1, true() ) -------------------------------- Ident, Value |- locs[PairL1.LocVarL] -> locs[PairL1_1.LocVarL], true() ; RecursiveSearchIntoTheLocalVariableList: setVariableIntoAPairList( Ident, Value |- PairL -> _, false() ) & Ident, Value |- LocVarL1 -> LocVarL1_1, TF -------------------------------- Ident, Value |- locs[PairL.LocVarL1] -> locs[PairL.LocVarL1_1], TF ; end setLocalVariable; set setAttributeOrStaticVariable is --SC: Assigns a value to an object attribute or a static variable. -- --JC: Object, Class variables, Current object reference --JC: |- Sought variable, Value to assign to this variable --JC: -> Updated object list, Updated class variable list --JC: (only one of these two lists is really updated). judgement Objects, ClassVariablesL, ObjectId |- Identifier, Val -> Objects, ClassVariablesL; AttributeAssignment: setAttribute( Ident, Value, ObjId |- ObjL1 -> ObjL1_1, true() ) -------------------------------- ObjL1, ClVarL, ObjId |- Ident, Value -> ObjL1_1, ClVarL ; ClassVariableAssignment: setAttribute( Ident, Value, ObjId |- ObjL -> _, false() ) & setClassVariable( ObjL, Ident, Value, ObjId |- ClVarL1 => ClVarL1_1 ) -------------------------------- ObjL, ClVarL1, ObjId |- Ident, Value -> ObjL, ClVarL1_1 ; end setAttributeOrStaticVariable; set setAttribute is --SC: Assigns a value to an attribute. -- --JC: Sought Variable, Value to assign to this latter variable --JC: Current object reference --JC: |- Object list --JC: -> Updated object list (if the variable was found, the same if not ), --JC: true or false depending on the result of the search of the variable --JC: into the list; judgement Identifier, Val, ObjectId |- Objects -> Objects, Bool; GoodObject_AssignTheValueToTheAttributeIfFound: setVariableIntoAPairList( Ident, Value |- PairL1 -> PairL1_1, TF ) -------------------------------- Ident, Value, ObjId |- objects[object(ObjId, Type, PairL1, Lock, WaitSet, Act).ObjL] -> objects[object(ObjId, Type, PairL1_1, Lock, WaitSet, Act).ObjL], TF ; RecursiveRule_NotTheGoodObject: Ident, Value, ObjId1 |- ObjL1 -> ObjL1_1, TF -------------------------------- Ident, Value, ObjId1 |- objects[object(ObjId2, Type, PairL, Lock, WaitSet, Act).ObjL1] -> objects[object(ObjId2, Type, PairL, Lock, WaitSet, Act).ObjL1_1], TF ; provided diff( ObjId2, ObjId1 ); end setAttribute; set setClassVariable is --SC: Assigns the given value to its class variable. -- --JC1: Class name of the class variable, Variable name, --JC1: Value to assign to this latter variable --JC1: |- Class variables --JC1: -> Updated class variable list judgement Identifier, Identifier, Val |- ClassVariablesL -> ClassVariablesL; --JC2: Objects, Sought variable, Value to assign to this latter variable, --JC2: Current object reference (will give the class name) --JC2: |- Class variable list --JC2: => Updated class variable list judgement Objects, Identifier, Val, ObjectId |- ClassVariablesL => ClassVariablesL; AssignValueToTheGivenClassVariable: setVariableIntoAPairList( Ident, Value |- PairL1 -> PairL1_1, true() ) -------------------------------- ClName, Ident, Value |- classVariablesL[classVariables(ClName, PairL1).ClVarL] -> classVariablesL[classVariables(ClName, PairL1_1).ClVarL] ; LookForTheRightClassBeforeTheAssignment: ClName1, Ident, Value |- ClVarL1 -> ClVarL1_1 -------------------------------- ClName1, Ident, Value |- classVariablesL[classVariables(ClName2, PairL).ClVarL1] -> classVariablesL[classVariables(ClName2, PairL).ClVarL1_1] ; provided diff( ClName1, ClName2 ); GetClassTypeBeforeTheAssignment: getObjectType( ObjId |- ObjL -> ClName ) & ClName, Ident, Value |- ClVarL1 -> ClVarL1_1 -------------------------------- ObjL, Ident, Value, ObjId |- ClVarL1 => ClVarL1_1 ; end setClassVariable; set evaluateArgument is --SC: Evaluates an argument list, making one step of evaluation of one --SC: argument at each use. -- --JC1: Objects, Class variables, environment of the current method --JC1: Current executing thread reference, Current object reference --JC1: Mode of execution of the method : static or not --JC1: |- Argument list --JC1: -> Updated objects, Updated class variables, Updated environment, --JC1: Updated complex argument list, instructions to execute at the next --JC1: execution step of the current thread judgement Objects, ClassVariablesL, Env, ObjectId, ObjectId, Identifier |- ArgumentList -> Objects, ClassVariablesL, Env, SemArguments, Insts; --JC2: Objects, Class variables, environment of the current method --JC2: Current executing thread reference, Current object reference --JC2: Mode of execution of the method : static or not --JC2: |- Complex argument list --JC2: => Updated objects, Updated class variables, Updated environment, --JC2: Updated complex argument list, instructions to execute at the next --JC2: execution step of the current thread judgement Objects, ClassVariablesL, Env, ObjectId, ObjectId, Identifier |- SemArguments => Objects, ClassVariablesL, Env, SemArguments, Insts; EmptyArgumentList: ObjL, ClVarL, Env, _, _, _ |- arguments[] -> ObjL, ClVarL, Env, semArguments[], insts[] ; ConvertArgumentsToCompArgumentsAndFirstStepCompArgumentEvaluation: convertArgumentsToCompArguments( ArgL -> CompArgL1 ) & ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- CompArgL1 => ObjL1_1, CLVarL1_1, Env1_1, CompArgL1_1, InstL -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ArgL -> ObjL1_1, CLVarL1_1, Env1_1, CompArgL1_1, InstL ; EmptyCompArgumentList_EvaluationEnd: ObjL, ClVarL, Env, _, _, _ |- semArguments[] => ObjL, ClVarL, Env, semArguments[], insts[] ; ValueAsFirstCompArgument_TailCompArgumentListEvaluation: ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- ExprL1 => ObjL1_1, ClVarL1_1, Env1_1, ExprL1_1, InstL & appendtree( semArguments[TVValue], ExprL1_1, ExprL2 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semArguments[TVValue.ExprL1] => ObjL1_1, ClVarL1_1, Env1_1, ExprL2, InstL ; -- !!! Why is the returned ThStatus thrown away? ExpressionEvaluation: evaluateExpression( ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- Expr1 -> ObjL1_1, ClVarL1_1, Env1_1, Expr1_1, InstL, _ ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semArguments[Expr1] => ObjL1_1, ClVarL1_1, Env1_1, semArguments[Expr1_1], InstL ; ExpressionAsFirstCompArgument_ExpressionEvaluation: ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semArguments[Expr1] => ObjL1_1, ClVarL1_1, Env1_1, ExprL2, InstL & appendtree( ExprL2, ExprL1, ExprL3 ) -------------------------------- ObjL1, ClVarL1, Env1, OThId, ObjId, Mode |- semArguments[Expr1.ExprL1] => ObjL1_1, ClVarL1_1, Env1_1, ExprL3, InstL ; provided diff( ExprL1, semArguments[] ); end evaluateArgument; set convertArgumentsToCompArguments is --SC: Converts a list of arguments into a comp argument list (useful for the --SC: representation of the object references during small-step evaluation). --SC: No argument evaluation is done during this conversion. -- --JC: Arguments -> Complex arguments judgement (ArgumentList -> SemArguments); EmptyArgumentList_ConversionEnd: (arguments[] -> semArguments[]) ; RecursiveConversionRule: (ArgL -> CompArgL) -------------------------------- (arguments[Arg.ArgL] -> semArguments[Arg.CompArgL]) ; end convertArgumentsToCompArguments; set convertCompArgumentsToValues is --SC: Converts a comp argument list into a value list. -- --JC: Complex arguments -> Values judgement (SemArguments -> Vals); EmptyCompArgumentList: (semArguments[] -> vals[]) ; RecursiveConversionRule: (CompArgL -> ValueL) -------------------------------- (semArguments[Value.CompArgL] -> vals[Value.ValueL]) ; end convertCompArgumentsToValues; set convertArrayInitializerToSemArgument is judgement (Type, ArrayInitializer -> SemArgument); convertVariableInitializersToSemArguments( Type, ArrayInit -> Exprs ) -------------------------------- (arrayof(Type), ArrayInit -> semNewInitializedArray(arrayof(Type), Exprs)) ; end convertArrayInitializerToSemArgument; set convertVariableInitializersToSemArguments is judgement (Type, ArrayInitializer -> SemArguments); (_, arrayInitializer[] -> semArguments[]) ; convertVariableInitializersToSemArguments( Type, VarInits -> Exprs ) -------------------------------- (Type, arrayInitializer[VarInit.VarInits] -> semArguments[VarInit.Exprs]) ; provided not_eq( VarInit, arrayInitializer[_] ); --RC: Recursive case, the variable initializer is an array initializer. convertArrayInitializerToSemArgument( Type, TVArrayInit -> Expr ) & convertVariableInitializersToSemArguments( Type, VarInits -> Exprs ) -------------------------------- (Type, arrayInitializer[TVArrayInit.VarInits] -> semArguments[Expr.Exprs]) ; end convertVariableInitializersToSemArguments; set makeNewArrayExprList is --SC: Builds semantic argument list of n expressions of the kind --SC: semNewArray(Type, Sizes). judgement (integer, Type, SemArguments -> SemArguments); (0, _, _ -> semArguments[]) ; --RC: recursive case. sub( n, 1, nminus1 ) & (nminus1, Type, Sizes -> Exprs) -------------------------------- (n, Type, Sizes -> semArguments[semNewArray(Type, Sizes).Exprs]) ; provided sup( n, 0 ); end makeNewArrayExprList; set convertDimsToSemArgs is --SC: Extract the expressions from a dimension list and make a semantic --SC: argument list out of them. judgement (Dims -> SemArguments); (dims[] -> semArguments[]) ; --RC: Recursive case. (Sizes -> Sizes_1) -------------------------------- (dims[Size.Sizes] -> semArguments[Size.Sizes_1]) ; end convertDimsToSemArgs; set computeArrayType is --SC: Computes the type of an array given the element type and a dimension --SC: list. judgement (Type, Dims -> Type); (Type, dims[] -> Type) ; --RC: Recursive case. (arrayof(Type), Dims -> ArrayType) -------------------------------- (Type, dims[_.Dims] -> ArrayType) ; end computeArrayType; set isValue is --SC: Checks if a SemExpression is a Value. judgement (SemExpression -> Bool); (true() -> true()) ; (false() -> true()) ; --RC: Integers are values. (integer _ -> true()) ; --RC: Floating point numbers are values. (floating _ -> true()) ; --RC: Characters are values. (character _ -> true()) ; --RC: Strings are values. (string _ -> true()) ; --RC: References are values. (objectId(_, _) -> true()) ; (null() -> true()) ; --RC: Finally, empty and exceptions are also values. --RC: (But exceptions probably should not be.) (empty() -> true()) ; (except(_, _, _) -> true()) ; --RC: Everything else is not a value. (Expr -> false()) ; provided not_eq( Expr, true() ) & not_eq( Expr, false() ) & not_eq( Expr, integer _ ) & not_eq( Expr, floating _ ) & not_eq( Expr, character _ ) & not_eq( Expr, string _ ) & not_eq( Expr, objectId(_, _) ) & not_eq( Expr, null() ) & not_eq( Expr, empty() ) & not_eq( Expr, except(_, _, _) ); end isValue; set allAreValues is --SC: Checks whether all arguments in a semantic argument list have been --SC: evaluated to values or not. judgement (SemArguments -> Bool); (semArguments[] -> true()) ; --RC: Recursive rule, non value found: isValue( Arg1 -> false() ) -------------------------------- (semArguments[Arg1.Args] -> false()) ; --RC: Recursive rule, only values so far: isValue( Arg1 -> true() ) & (Args -> TF) -------------------------------- (semArguments[Arg1.Args] -> TF) ; end allAreValues; set isCompoundAssignOp is --SC: Checks whether an AssignOperator is a compund assignment operator --SC: (+=, -=, etc.) or not. judgement (AssignOperator -> Bool); (plusAssignment() -> true()) ; (minusAssignment() -> true()) ; (timesAssignment() -> true()) ; (divAssignment() -> true()) ; (modAssignment() -> true()) ; (xorAssignment() -> true()) ; (andAssignment() -> true()) ; (iorAssignment() -> true()) ; (leftShiftAssignment() -> true()) ; (rightShiftAssignment() -> true()) ; (unsignedRightShiftAssignment() -> true()) ; (AOp -> false()) ; provided not_eq( AOp, plusAssignment() ) & not_eq( AOp, minusAssignment() ) & not_eq( AOp, timesAssignment() ) & not_eq( AOp, divAssignment() ) & not_eq( AOp, modAssignment() ) & not_eq( AOp, xorAssignment() ) & not_eq( AOp, andAssignment() ) & not_eq( AOp, iorAssignment() ) & not_eq( AOp, leftShiftAssignment() ) & not_eq( AOp, rightShiftAssignment() ) & not_eq( AOp, unsignedRightShiftAssignment() ); end isCompoundAssignOp; set getOpFromCompundAssignOp is --SC: Gets the binary numeric operator (+, -, etc.) from a compound --SC: assignment operator (+=, -=, etc.). judgement (AssignOperator -> BinaryOperator); (plusAssignment() -> plus()) ; (minusAssignment() -> minus()) ; (timesAssignment() -> times()) ; (divAssignment() -> div()) ; (modAssignment() -> mod()) ; (xorAssignment() -> xor()) ; (andAssignment() -> and()) ; (iorAssignment() -> ior()) ; (leftShiftAssignment() -> leftShift()) ; (rightShiftAssignment() -> rightShift()) ; (unsignedRightShiftAssignment() -> unsignedRightShift()) ; end getOpFromCompundAssignOp; end java_expr_evaluation