Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346/****************************************************************************1**2*W exprs.c GAP source Martin Schönert3**4**5*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany6*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland7*Y Copyright (C) 2002 The GAP Group8**9** This file contains the functions of the expressions package.10**11** The expressions package is the part of the interpreter that evaluates12** expressions to their values and prints expressions.13*/14#include "system.h" /* Ints, UInts */151617#include "gasman.h" /* garbage collector */18#include "objects.h" /* objects */19#include "scanner.h" /* scanner */2021#include "gap.h" /* error handling, initialisation */2223#include "gvars.h" /* global variables */2425#include "ariths.h" /* basic arithmetic */26#include "records.h" /* generic records */27#include "lists.h" /* generic lists */2829#include "bool.h" /* booleans */30#include "integer.h" /* integers */3132#include "permutat.h" /* permutations */33#include "trans.h" /* transformations */34#include "pperm.h" /* partial perms */3536#include "precord.h" /* plain records */3738#include "plist.h" /* plain lists */39#include "range.h" /* ranges */40#include "string.h" /* strings */4142#include "code.h" /* coder */43#include "calls.h"44#include "stats.h"454647#include "exprs.h" /* expressions */4849#include "tls.h" /* thread-local storage */50#include "profile.h" /* installing methods */51#include "aobjects.h" /* atomic objects */5253#include "vars.h" /* variables */5455#include <assert.h>565758/****************************************************************************59**6061*F OBJ_REFLVAR(<expr>) . . . . . . . . . . . value of a reference to a local62**63** 'OBJ_REFLVAR' returns the value of the reference to a local variable64** <expr>.65**66** 'OBJ_REFLVAR' is defined in the declaration part of this package as67** follows68**69#ifdef NO_LVAR_CHECKS70#define OBJ_REFLVAR(expr) \71OBJ_LVAR( LVAR_REFLVAR( (expr) ) )72#endif73#ifndef NO_LVAR_CHECKS74#define OBJ_REFLVAR(expr) \75(*(Obj*)(((char*)TLS(PtrLVars))+(expr)+5) != 0 ? \76*(Obj*)(((char*)TLS(PtrLVars))+(expr)+5) : \77ObjLVar( LVAR_REFLVAR( expr ) ) )78#endif79*/808182/****************************************************************************83**84*F OBJ_INTEXPR(<expr>) . . . . . . . . . . . value of an integer expression85**86** 'OBJ_INTEXPR' returns the (immediate) integer value of the (immediate)87** integer expression <expr>.88**89** 'OBJ_INTEXPR(<expr>)' should be 'OBJ_INT(INT_INTEXPR(<expr>))', but for90** performance reasons we implement it as '(Obj)(<expr>)'. This is of91** course highly dependent on (immediate) integer expressions and92** (immediate) integer values having the same representation.93**94** 'OBJ_INTEXPR' is defined in the declaration part of this package as95** follow96**97#define OBJ_INTEXPR(expr) \98((Obj)(Int)(Int4)(expr))99*/100101102/****************************************************************************103**104*F EVAL_EXPR(<expr>) . . . . . . . . . . . . . . . . evaluate an expression105**106** 'EVAL_EXPR' evaluates the expression <expr>.107**108** 'EVAL_EXPR' returns the value of <expr>.109**110** 'EVAL_EXPR' causes the evaluation of <expr> by dispatching to the111** evaluator, i.e., to the function that evaluates expressions of the type112** of <expr>.113**114** Note that 'EVAL_EXPR' does not use 'TNUM_EXPR', since it also handles the115** two special cases that 'TNUM_EXPR' handles.116**117** 'EVAL_EXPR' is defined in the declaration part of this package as follows:118**119#define EVAL_EXPR(expr) \120(IS_REFLVAR(expr) ? OBJ_REFLVAR(expr) : \121(IS_INTEXPR(expr) ? OBJ_INTEXPR(expr) : \122(*EvalExprFuncs[ TNUM_STAT(expr) ])( expr ) ))123*/124125126/****************************************************************************127**128*V EvalExprFuncs[<type>] . . . . . evaluator for expressions of type <type>129**130** 'EvalExprFuncs' is the dispatch table that contains for every type of131** expressions a pointer to the evaluator for expressions of this type,132** i.e., the function that should be called to evaluate expressions of this133** type.134*/135Obj (* EvalExprFuncs [256]) ( Expr expr );136137138/****************************************************************************139**140*F EVAL_BOOL_EXPR(<expr>) . . . . evaluate an expression to a boolean value141**142** 'EVAL_BOOL_EXPR' evaluates the expression <expr> and checks that the143** value is either 'true' or 'false'. If the expression does not evaluate144** to 'true' or 'false', then an error is signalled.145**146** 'EVAL_BOOL_EXPR' returns the value of <expr> (which is either 'true' or147** 'false').148**149** 'EVAL_BOOL_EXPR' is defined in the declaration part of this package as150** follows151**152#define EVAL_BOOL_EXPR(expr) \153( (*EvalBoolFuncs[ TNUM_EXPR( expr ) ])( expr ) )154*/155156157/****************************************************************************158**159*V EvalBoolFuncs[<type>] . . boolean evaluator for expression of type <type>160**161** 'EvalBoolFuncs' is the dispatch table that contains for every type of162** expression a pointer to a boolean evaluator for expressions of this type,163** i.e., a pointer to a function which is guaranteed to return a boolean164** value that should be called to evaluate expressions of this type.165*/166Obj (* EvalBoolFuncs [256]) ( Expr expr );167168169/****************************************************************************170**171*F EvalUnknownExpr(<expr>) . . . . . . . evaluate expression of unknown type172**173** 'EvalUnknownExpr' is the evaluator that is called if an attempt is made174** to evaluate an expression <expr> of an unknown type. It signals an175** error. If this is ever called, then GAP is in serious trouble, such as176** an overwritten type field of an expression.177*/178Obj EvalUnknownExpr (179Expr expr )180{181Pr( "Panic: tried to evaluate an expression of unknown type '%d'\n",182(Int)TNUM_EXPR(expr), 0L );183return 0;184}185186187/****************************************************************************188**189*F EvalUnknownBool(<expr>) . . . . boolean evaluator for general expressions190**191** 'EvalUnknownBool' evaluates the expression <expr> (using 'EVAL_EXPR'),192** and checks that the value is either 'true' or 'false'. If the expression193** does not evaluate to 'true' or 'false', then an error is signalled.194**195** This is the default function in 'EvalBoolFuncs' used for expressions that196** are not a priori known to evaluate to a boolean value (such as197** function calls).198*/199Obj EvalUnknownBool (200Expr expr )201{202Obj val; /* value, result */203204/* evaluate the expression */205val = EVAL_EXPR( expr );206207/* check that the value is either 'true' or 'false' */208while ( val != True && val != False ) {209val = ErrorReturnObj(210"<expr> must be 'true' or 'false' (not a %s)",211(Int)TNAM_OBJ(val), 0L,212"you can replace <expr> via 'return <expr>;'" );213}214215/* return the value */216return val;217}218219220/****************************************************************************221**222*F EvalOr(<expr>) . . . . . . . . . . . . . evaluate a boolean or operation223**224** 'EvalOr' evaluates the or-expression <expr> and returns its value, i.e.,225** 'true' if either of the operands is 'true', and 'false' otherwise.226** 'EvalOr' is called from 'EVAL_EXPR' to evaluate expressions of type227** 'T_OR'.228**229** If '<expr>.left' is already 'true' 'EvalOr' returns 'true' without230** evaluating '<expr>.right'. This allows constructs like231**232** if (index > max) or (list[index] = 0) then ... fi;233*/234Obj EvalOr (235Expr expr )236{237Obj opL; /* evaluated left operand */238Expr tmp; /* temporary expression */239240/* evaluate and test the left operand */241tmp = ADDR_EXPR(expr)[0];242opL = EVAL_BOOL_EXPR( tmp );243if ( opL != False ) {244return True;245}246247/* evaluate and test the right operand */248tmp = ADDR_EXPR(expr)[1];249return EVAL_BOOL_EXPR( tmp );250}251252253/****************************************************************************254**255*F EvalAnd(<expr>) . . . . . . . . . . . . evaluate a boolean and operation256**257** 'EvalAnd' evaluates the and-expression <expr> and returns its value,258** i.e., 'true' if both operands are 'true', and 'false' otherwise.259** 'EvalAnd' is called from 'EVAL_EXPR' to evaluate expressions of type260** 'T_AND'.261**262** If '<expr>.left' is already 'false' 'EvalAnd' returns 'false' without263** evaluating '<expr>.right'. This allows constructs like264**265** if (index <= max) and (list[index] = 0) then ... fi;266*/267extern Obj NewAndFilter (268Obj oper1,269Obj oper2 );270271Obj EvalAnd (272Expr expr )273{274Obj opL; /* evaluated left operand */275Obj opR; /* evaluated right operand */276Expr tmp; /* temporary expression */277278/* if the left operand is 'false', this is the result */279tmp = ADDR_EXPR(expr)[0];280opL = EVAL_EXPR( tmp );281if ( opL == False ) {282return opL;283}284285/* if the left operand is 'true', the result is the right operand */286else if ( opL == True ) {287tmp = ADDR_EXPR(expr)[1];288return EVAL_BOOL_EXPR( tmp );289}290291/* handle the 'and' of two filters */292else if ( TNUM_OBJ(opL) == T_FUNCTION ) {293tmp = ADDR_EXPR(expr)[1];294opR = EVAL_EXPR( tmp );295if ( TNUM_OBJ(opR) == T_FUNCTION ) {296return NewAndFilter( opL, opR );297}298else {299ErrorQuit(300"<expr> must be 'true' or 'false' (not a %s)",301(Int)TNAM_OBJ(opL), 0L );302}303}304305/* signal an error */306else {307ErrorQuit(308"<expr> must be 'true' or 'false' (not a %s)",309(Int)TNAM_OBJ(opL), 0L );310}311312/* please 'lint' */313return 0;314}315316317/****************************************************************************318**319*F EvalNot(<expr>) . . . . . . . . . . . . . . . . . negate a boolean value320**321** 'EvalNot' evaluates the not-expression <expr> and returns its value,322** i.e., 'true' if the operand is 'false', and 'false' otherwise. 'EvalNot'323** is called from 'EVAL_EXPR' to evaluate expressions of type 'T_NOT'.324*/325Obj EvalNot (326Expr expr )327{328Obj val; /* value, result */329Obj op; /* evaluated operand */330Expr tmp; /* temporary expression */331332/* evaluate the operand to a boolean */333tmp = ADDR_EXPR(expr)[0];334op = EVAL_BOOL_EXPR( tmp );335336/* compute the negation */337val = (op == False ? True : False);338339/* return the negated value */340return val;341}342343344/****************************************************************************345**346*F EvalEq(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison347**348** 'EvalEq' evaluates the equality-expression <expr> and returns its value,349** i.e., 'true' if the operand '<expr>.left' is equal to the operand350** '<expr>.right' and 'false' otherwise. 'EvalEq' is called from351** 'EVAL_EXPR' to evaluate expressions of type 'T_EQ'.352**353** 'EvalEq' evaluates the operands and then calls the 'EQ' macro.354*/355Obj EvalEq (356Expr expr )357{358Obj val; /* value, result */359Obj opL; /* evaluated left operand */360Obj opR; /* evaluated right operand */361Expr tmp; /* temporary expression */362363/* get the operands */364tmp = ADDR_EXPR(expr)[0];365opL = EVAL_EXPR( tmp );366tmp = ADDR_EXPR(expr)[1];367opR = EVAL_EXPR( tmp );368369/* compare the operands */370SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */371val = (EQ( opL, opR ) ? True : False);372373/* return the value */374return val;375}376377378/****************************************************************************379**380*F EvalNe(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison381**382** 'EvalNe' evaluates the comparison-expression <expr> and returns its383** value, i.e., 'true' if the operand '<expr>.left' is not equal to the384** operand '<expr>.right' and 'false' otherwise. 'EvalNe' is called from385** 'EVAL_EXPR' to evaluate expressions of type 'T_LT'.386**387** 'EvalNe' is simply implemented as 'not <objL> = <objR>'.388*/389Obj EvalNe (390Expr expr )391{392Obj val; /* value, result */393Obj opL; /* evaluated left operand */394Obj opR; /* evaluated right operand */395Expr tmp; /* temporary expression */396397/* get the operands */398tmp = ADDR_EXPR(expr)[0];399opL = EVAL_EXPR( tmp );400tmp = ADDR_EXPR(expr)[1];401opR = EVAL_EXPR( tmp );402403/* compare the operands */404SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */405val = (EQ( opL, opR ) ? False : True);406407/* return the value */408return val;409}410411412/****************************************************************************413**414*F EvalLt(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison415**416** 'EvalLt' evaluates the comparison-expression <expr> and returns its417** value, i.e., 'true' if the operand '<expr>.left' is less than the operand418** '<expr>.right' and 'false' otherwise. 'EvalLt' is called from419** 'EVAL_EXPR' to evaluate expressions of type 'T_LT'.420**421** 'EvalLt' evaluates the operands and then calls the 'LT' macro.422*/423Obj EvalLt (424Expr expr )425{426Obj val; /* value, result */427Obj opL; /* evaluated left operand */428Obj opR; /* evaluated right operand */429Expr tmp; /* temporary expression */430431/* get the operands */432tmp = ADDR_EXPR(expr)[0];433opL = EVAL_EXPR( tmp );434tmp = ADDR_EXPR(expr)[1];435opR = EVAL_EXPR( tmp );436437/* compare the operands */438SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */439val = (LT( opL, opR ) ? True : False);440441/* return the value */442return val;443}444445446/****************************************************************************447**448*F EvalGe(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison449**450** 'EvalGe' evaluates the comparison-expression <expr> and returns its451** value, i.e., 'true' if the operand '<expr>.left' is greater than or equal452** to the operand '<expr>.right' and 'false' otherwise. 'EvalGe' is called453** from 'EVAL_EXPR' to evaluate expressions of type 'T_GE'.454**455** 'EvalGe' is simply implemented as 'not <objL> < <objR>'.456*/457Obj EvalGe (458Expr expr )459{460Obj val; /* value, result */461Obj opL; /* evaluated left operand */462Obj opR; /* evaluated right operand */463Expr tmp; /* temporary expression */464465/* get the operands */466tmp = ADDR_EXPR(expr)[0];467opL = EVAL_EXPR( tmp );468tmp = ADDR_EXPR(expr)[1];469opR = EVAL_EXPR( tmp );470471/* compare the operands */472SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */473val = (LT( opL, opR ) ? False : True);474475/* return the value */476return val;477}478479480/****************************************************************************481**482*F EvalGt(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison483**484** 'EvalGt' evaluates the comparison-expression <expr> and returns its485** value, i.e., 'true' if the operand '<expr>.left' is greater than the486** operand '<expr>.right' and 'false' otherwise. 'EvalGt' is called from487** 'EVAL_EXPR' to evaluate expressions of type 'T_GT'.488**489** 'EvalGt' is simply implemented as '<objR> < <objL>'.490*/491Obj EvalGt (492Expr expr )493{494Obj val; /* value, result */495Obj opL; /* evaluated left operand */496Obj opR; /* evaluated right operand */497Expr tmp; /* temporary expression */498499/* get the operands */500tmp = ADDR_EXPR(expr)[0];501opL = EVAL_EXPR( tmp );502tmp = ADDR_EXPR(expr)[1];503opR = EVAL_EXPR( tmp );504505/* compare the operands */506SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */507val = (LT( opR, opL ) ? True : False);508509/* return the value */510return val;511}512513514/****************************************************************************515**516*F EvalLe(<expr>) . . . . . . . . . . . . . . . . . . evaluate a comparison517**518** 'EvalLe' evaluates the comparison-expression <expr> and returns its519** value, i.e., 'true' if the operand '<expr>.left' is less or equal to the520** operand '<expr>.right' and 'false' otherwise. 'EvalLe' is called from521** 'EVAL_EXPR' to evaluate expressions of type 'T_LE'.522**523** 'EvalLe' is simply implemented as 'not <objR> < <objR>'.524*/525Obj EvalLe (526Expr expr )527{528Obj val; /* value, result */529Obj opL; /* evaluated left operand */530Obj opR; /* evaluated right operand */531Expr tmp; /* temporary expression */532533/* get the operands */534tmp = ADDR_EXPR(expr)[0];535opL = EVAL_EXPR( tmp );536tmp = ADDR_EXPR(expr)[1];537opR = EVAL_EXPR( tmp );538539/* compare the operands */540SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */541val = (LT( opR, opL ) ? False : True);542543/* return the value */544return val;545}546547548/****************************************************************************549**550*F EvalIn(<in>) . . . . . . . . . . . . . . . test for membership in a list551**552** 'EvalIn' evaluates the in-expression <expr> and returns its value, i.e.,553** 'true' if the operand '<expr>.left' is a member of '<expr>.right' and554** 'false' otherwise. 'EvalIn' is called from 'EVAL_EXPR' to evaluate555** expressions of type 'T_IN'.556*/557Obj EvalIn (558Expr expr )559{560Obj val; /* value, result */561Obj opL; /* evaluated left operand */562Obj opR; /* evaluated right operand */563Expr tmp; /* temporary expression */564565/* evaluate <opL> */566tmp = ADDR_EXPR(expr)[0];567opL = EVAL_EXPR( tmp );568569/* evaluate <opR> */570tmp = ADDR_EXPR(expr)[1];571opR = EVAL_EXPR( tmp );572573/* perform the test */574SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */575val = (IN( opL, opR ) ? True : False);576577/* return the value */578return val;579}580581582/****************************************************************************583**584*F EvalSum(<expr>) . . . . . . . . . . . . . . . . . . . . . evaluate a sum585**586** 'EvalSum' evaluates the sum-expression <expr> and returns its value,587** i.e., the sum of the two operands '<expr>.left' and '<expr>.right'.588** 'EvalSum' is called from 'EVAL_EXPR' to evaluate expressions of type589** 'T_SUM'.590**591** 'EvalSum' evaluates the operands and then calls the 'SUM' macro.592*/593Obj EvalSum (594Expr expr )595{596Obj val; /* value, result */597Obj opL; /* evaluated left operand */598Obj opR; /* evaluated right operand */599Expr tmp; /* temporary expression */600601/* get the operands */602tmp = ADDR_EXPR(expr)[0];603opL = EVAL_EXPR( tmp );604tmp = ADDR_EXPR(expr)[1];605opR = EVAL_EXPR( tmp );606607/* first try to treat the operands as small integers with small result */608if ( ! ARE_INTOBJS( opL, opR ) || ! SUM_INTOBJS( val, opL, opR ) ) {609610/* if that doesn't work, dispatch to the addition function */611SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */612val = SUM( opL, opR );613614}615616/* return the value */617return val;618}619620621/****************************************************************************622**623*F EvalAInv(<expr>) . . . . . . . . . . . . . . evaluate a additive inverse624**625** 'EvalAInv' evaluates the additive inverse-expression and returns its626** value, i.e., the additive inverse of the operand. 'EvalAInv' is called627** from 'EVAL_EXPR' to evaluate expressions of type 'T_AINV'.628**629** 'EvalAInv' evaluates the operand and then calls the 'AINV' macro.630*/631Obj EvalAInv (632Expr expr )633{634Obj val; /* value, result */635Obj opL; /* evaluated left operand */636Expr tmp; /* temporary expression */637638/* get the operands */639tmp = ADDR_EXPR(expr)[0];640opL = EVAL_EXPR( tmp );641642/* compute the additive inverse */643SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */644val = AINV( opL );645646/* return the value */647return val;648}649650651/****************************************************************************652**653*F EvalDiff(<expr>) . . . . . . . . . . . . . . . . . evaluate a difference654**655** 'EvalDiff' evaluates the difference-expression <expr> and returns its656** value, i.e., the difference of the two operands '<expr>.left' and657** '<expr>.right'. 'EvalDiff' is called from 'EVAL_EXPR' to evaluate658** expressions of type 'T_DIFF'.659**660** 'EvalDiff' evaluates the operands and then calls the 'DIFF' macro.661*/662Obj EvalDiff (663Expr expr )664{665Obj val; /* value, result */666Obj opL; /* evaluated left operand */667Obj opR; /* evaluated right operand */668Expr tmp; /* temporary expression */669670/* get the operands */671tmp = ADDR_EXPR(expr)[0];672opL = EVAL_EXPR( tmp );673tmp = ADDR_EXPR(expr)[1];674opR = EVAL_EXPR( tmp );675676/* first try to treat the operands as small integers with small result */677if ( ! ARE_INTOBJS( opL, opR ) || ! DIFF_INTOBJS( val, opL, opR ) ) {678679/* if that doesn't work, dispatch to the subtraction function */680SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */681val = DIFF( opL, opR );682683}684685/* return the value */686return val;687}688689690/****************************************************************************691**692*F EvalProd(<expr>) . . . . . . . . . . . . . . . . . . evaluate a product693**694** 'EvalProd' evaluates the product-expression <expr> and returns it value,695** i.e., the product of the two operands '<expr>.left' and '<expr>.right'.696** 'EvalProd' is called from 'EVAL_EXPR' to evaluate expressions of type697** 'T_PROD'.698**699** 'EvalProd' evaluates the operands and then calls the 'PROD' macro.700*/701Obj EvalProd (702Expr expr )703{704Obj val; /* result */705Obj opL; /* evaluated left operand */706Obj opR; /* evaluated right operand */707Expr tmp; /* temporary expression */708709/* get the operands */710tmp = ADDR_EXPR(expr)[0];711opL = EVAL_EXPR( tmp );712tmp = ADDR_EXPR(expr)[1];713opR = EVAL_EXPR( tmp );714715/* first try to treat the operands as small integers with small result */716if ( ! ARE_INTOBJS( opL, opR ) || ! PROD_INTOBJS( val, opL, opR ) ) {717718/* if that doesn't work, dispatch to the multiplication function */719SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */720val = PROD( opL, opR );721722}723724/* return the value */725return val;726}727728729/****************************************************************************730**731*F EvalInv(<expr>) . . . . . . . . . . . . evaluate a multiplicative inverse732**733** 'EvalInv' evaluates the multiplicative inverse-expression and returns its734** value, i.e., the multiplicative inverse of the operand. 'EvalInv' is735** called from 'EVAL_EXPR' to evaluate expressions of type 'T_INV'.736**737** 'EvalInv' evaluates the operand and then calls the 'INV' macro.738*/739Obj EvalInv (740Expr expr )741{742Obj val; /* value, result */743Obj opL; /* evaluated left operand */744Expr tmp; /* temporary expression */745746/* get the operands */747tmp = ADDR_EXPR(expr)[0];748opL = EVAL_EXPR( tmp );749750/* compute the multiplicative inverse */751SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */752val = INV_MUT( opL );753754/* return the value */755return val;756}757758759/****************************************************************************760**761*F EvalQuo(<expr>) . . . . . . . . . . . . . . . . . . . evaluate a quotient762**763** 'EvalQuo' evaluates the quotient-expression <expr> and returns its value,764** i.e., the quotient of the two operands '<expr>.left' and '<expr>.right'.765** 'EvalQuo' is called from 'EVAL_EXPR' to evaluate expressions of type766** 'T_QUO'.767**768** 'EvalQuo' evaluates the operands and then calls the 'QUO' macro.769*/770Obj EvalQuo (771Expr expr )772{773Obj val; /* value, result */774Obj opL; /* evaluated left operand */775Obj opR; /* evaluated right operand */776Expr tmp; /* temporary expression */777778/* get the operands */779tmp = ADDR_EXPR(expr)[0];780opL = EVAL_EXPR( tmp );781tmp = ADDR_EXPR(expr)[1];782opR = EVAL_EXPR( tmp );783784/* dispatch to the division function */785SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */786val = QUO( opL, opR );787788/* return the value */789return val;790}791792793/****************************************************************************794**795*F EvalMod(<expr>) . . . . . . . . . . . . . . . . . . evaluate a remainder796**797** 'EvalMod' evaluates the remainder-expression <expr> and returns its798** value, i.e., the remainder of the two operands '<expr>.left' and799** '<expr>.right'. 'EvalMod' is called from 'EVAL_EXPR' to evaluate800** expressions of type 'T_MOD'.801**802** 'EvalMod' evaluates the operands and then calls the 'MOD' macro.803*/804Obj EvalMod (805Expr expr )806{807Obj val; /* value, result */808Obj opL; /* evaluated left operand */809Obj opR; /* evaluated right operand */810Expr tmp; /* temporary expression */811812/* get the operands */813tmp = ADDR_EXPR(expr)[0];814opL = EVAL_EXPR( tmp );815tmp = ADDR_EXPR(expr)[1];816opR = EVAL_EXPR( tmp );817818/* dispatch to the remainder function */819SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */820val = MOD( opL, opR );821822/* return the value */823return val;824}825826827/****************************************************************************828**829*F EvalPow(<expr>) . . . . . . . . . . . . . . . . . . . . evaluate a power830**831** 'EvalPow' evaluates the power-expression <expr> and returns its value,832** i.e., the power of the two operands '<expr>.left' and '<expr>.right'.833** 'EvalPow' is called from 'EVAL_EXPR' to evaluate expressions of type834** 'T_POW'.835**836** 'EvalPow' evaluates the operands and then calls the 'POW' macro.837*/838Obj EvalPow (839Expr expr )840{841Obj val; /* value, result */842Obj opL; /* evaluated left operand */843Obj opR; /* evaluated right operand */844Expr tmp; /* temporary expression */845846/* get the operands */847tmp = ADDR_EXPR(expr)[0];848opL = EVAL_EXPR( tmp );849tmp = ADDR_EXPR(expr)[1];850opR = EVAL_EXPR( tmp );851852/* dispatch to the powering function */853SET_BRK_CALL_TO(expr); /* Note possible call for FuncWhere */854val = POW( opL, opR );855856/* return the value */857return val;858}859860861/****************************************************************************862**863*F EvalIntExpr(<expr>) . . . . . . . . . evaluate literal integer expression864**865** 'EvalIntExpr' evaluates the literal integer expression <expr> and returns866** its value.867*/868#define IDDR_EXPR(expr) ((UInt2*)ADDR_EXPR(expr))869870Obj EvalIntExpr (871Expr expr )872{873Obj val; /* integer, result */874875876/* allocate the integer */877val = NewBag( ((UInt *)ADDR_EXPR(expr))[0], SIZE_EXPR(expr)-sizeof(UInt));878memcpy((void *)ADDR_OBJ(val), (void *)(((UInt *)ADDR_EXPR(expr))+1), (size_t) (SIZE_EXPR(expr)-sizeof(UInt)));879880/* return the value */881return val;882}883884885/****************************************************************************886**887*F EvalTrueExpr(<expr>) . . . . . . . . . evaluate literal true expression888**889** 'EvalTrueExpr' evaluates the literal true expression <expr> and returns890** its value (True).891*/892Obj EvalTrueExpr (893Expr expr )894{895return True;896}897898899/****************************************************************************900**901*F EvalFalseExpr(<expr>) . . . . . . . . . evaluate literal false expression902**903** 'EvalFalseExpr' evaluates the literal false expression <expr> and returns904** its value (False).905*/906Obj EvalFalseExpr (907Expr expr )908{909return False;910}911912913/****************************************************************************914**915*F EvalCharExpr(<expr>) . . . . . . evaluate a literal character expression916**917** 'EvalCharExpr' evaluates the literal character expression <expr> and918** returns its value.919*/920Obj EvalCharExpr (921Expr expr )922{923return ObjsChar[ ((UChar*)ADDR_EXPR(expr))[0] ];924}925926927/****************************************************************************928**929*F EvalPermExpr(<expr>) . . . . . . . . . evaluate a permutation expression930**931** 'EvalPermExpr' evaluates the permutation expression <expr>.932*/933Obj EvalPermExpr (934Expr expr )935{936Obj perm; /* permutation, result */937UInt4 * ptr4; /* pointer into perm */938UInt2 * ptr2; /* pointer into perm */939Obj val; /* one entry as value */940UInt c, p, l; /* entries in permutation */941UInt m; /* maximal entry in permutation */942Expr cycle; /* one cycle of permutation */943UInt i, j, k; /* loop variable */944945/* special case for identity permutation */946if ( SIZE_EXPR(expr) == 0 ) {947return IdentityPerm;948}949950/* allocate the new permutation */951m = 0;952perm = NEW_PERM4( 0 );953954/* loop over the cycles */955for ( i = 1; i <= SIZE_EXPR(expr)/sizeof(Expr); i++ ) {956cycle = ADDR_EXPR(expr)[i-1];957958/* loop over the entries of the cycle */959c = p = l = 0;960for ( j = SIZE_EXPR(cycle)/sizeof(Expr); 1 <= j; j-- ) {961962/* get and check current entry for the cycle */963val = EVAL_EXPR( ADDR_EXPR( cycle )[j-1] );964while ( ! IS_INTOBJ(val) || INT_INTOBJ(val) <= 0 ) {965val = ErrorReturnObj(966"Permutation: <expr> must be a positive integer (not a %s)",967(Int)TNAM_OBJ(val), 0L,968"you can replace <expr> via 'return <expr>;'" );969}970c = INT_INTOBJ(val);971972/* if necessary resize the permutation */973if ( SIZE_OBJ(perm)/sizeof(UInt4) < c ) {974ResizeBag( perm, (c + 1023) / 1024 * 1024 * sizeof(UInt4) );975ptr4 = ADDR_PERM4( perm );976for ( k = m+1; k <= SIZE_OBJ(perm)/sizeof(UInt4); k++ ) {977ptr4[k-1] = k-1;978}979}980if ( m < c ) {981m = c;982}983984/* check that the cycles are disjoint */985ptr4 = ADDR_PERM4( perm );986if ( (p != 0 && p == c) || (ptr4[c-1] != c-1) ) {987return ErrorReturnObj(988"Permutation: cycles must be disjoint",9890L, 0L,990"you can replace permutation <perm> via 'return <perm>;'" );991}992993/* enter the previous entry at current location */994ptr4 = ADDR_PERM4( perm );995if ( p != 0 ) { ptr4[c-1] = p-1; }996else { l = c; }997998/* remember current entry for next round */999p = c;1000}10011002/* enter first (last popped) entry at last (first popped) location */1003ptr4 = ADDR_PERM4( perm );1004ptr4[l-1] = p-1;10051006}10071008/* if possible represent the permutation with short entries */1009if ( m <= 65536UL ) {1010ptr2 = ADDR_PERM2( perm );1011ptr4 = ADDR_PERM4( perm );1012for ( k = 1; k <= m; k++ ) {1013ptr2[k-1] = ptr4[k-1];1014};1015RetypeBag( perm, T_PERM2 );1016ResizeBag( perm, m * sizeof(UInt2) );1017}10181019/* otherwise just shorten the permutation */1020else {1021ResizeBag( perm, m * sizeof(UInt4) );1022}10231024/* return the permutation */1025return perm;1026}102710281029/****************************************************************************1030**1031*F EvalListExpr(<expr>) . . . . . evaluate list expression to a list value1032**1033** 'EvalListExpr' evaluates the list expression, i.e., not yet evaluated1034** list, <expr> to a list value.1035**1036** 'EvalListExpr' just calls 'ListExpr1' and 'ListExpr2' to evaluate the1037** list expression.1038*/1039Obj ListExpr1 ( Expr expr );1040void ListExpr2 ( Obj list, Expr expr );1041Obj RecExpr1 ( Expr expr );1042void RecExpr2 ( Obj rec, Expr expr );10431044Obj EvalListExpr (1045Expr expr )1046{1047Obj list; /* list value, result */10481049/* evalute the list expression */1050list = ListExpr1( expr );1051ListExpr2( list, expr );10521053/* return the result */1054return list;1055}105610571058/****************************************************************************1059**1060*F EvalListTildeExpr(<expr>) . . . . evaluate a list expression with a tilde1061**1062** 'EvalListTildeExpr' evaluates the list expression, i.e., not yet1063** evaluated list, <expr> to a list value. The difference to 'EvalListExpr'1064** is that in <expr> there are occurrences of '~' referring to this list1065** value.1066**1067** 'EvalListTildeExpr' just calls 'ListExpr1' to create the list, assigns1068** the list to the variable '~', and finally calls 'ListExpr2' to evaluate1069** the subexpressions into the list. Thus subexpressions in the list1070** expression can refer to this variable and its subobjects to create1071** objects that are not trees.1072*/1073Obj EvalListTildeExpr (1074Expr expr )1075{1076Obj list; /* list value, result */1077Obj tilde; /* old value of tilde */10781079/* remember the old value of '~' */1080tilde = VAL_GVAR( Tilde );10811082/* create the list value */1083list = ListExpr1( expr );10841085/* assign the list to '~' */1086AssGVar( Tilde, list );10871088/* evaluate the subexpressions into the list value */1089ListExpr2( list, expr );10901091/* restore old value of '~' */1092AssGVar( Tilde, tilde );10931094/* return the list value */1095return list;1096}109710981099/****************************************************************************1100**1101*F ListExpr1(<expr>) . . . . . . . . . . . make a list for a list expression1102*F ListExpr2(<list>,<expr>) . . . enter the sublists for a list expression1103**1104** 'ListExpr1' and 'ListExpr2' together evaluate the list expression <expr>1105** into the list <list>.1106**1107** 'ListExpr1' allocates a new plain list of the same size as the list1108** expression <expr> and returns this list.1109**1110** 'ListExpr2' evaluates the subexpression of <expr> and puts the values1111** into the list <list> (which should be a plain list of the same size as1112** the list expression <expr>, e.g., the one allocated by 'ListExpr1').1113**1114** This two step allocation is necessary, because list expressions such as1115** '[ [1], ~[1] ]' requires that the value of one subexpression is entered1116** into the list value before the next subexpression is evaluated.1117*/1118Obj ListExpr1 (1119Expr expr )1120{1121Obj list; /* list value, result */1122Int len; /* logical length of the list */11231124/* get the length of the list */1125len = SIZE_EXPR(expr) / sizeof(Expr);11261127/* allocate the list value */1128if ( 0 == len ) {1129list = NEW_PLIST( T_PLIST_EMPTY, len );1130}1131else {1132list = NEW_PLIST( T_PLIST, len );1133}1134SET_LEN_PLIST( list, len );11351136/* return the list */1137return list;1138}11391140void ListExpr2 (1141Obj list,1142Expr expr )1143{1144Obj sub; /* value of a subexpression */1145Int len; /* logical length of the list */1146Int i; /* loop variable */1147Int posshole; /* initially 0, set to 1 at1148first empty position, then1149next full position causes1150the list to be made1151non-dense */11521153/* get the length of the list */1154len = SIZE_EXPR(expr) / sizeof(Expr);11551156/* initially we have not seen a hole */1157posshole = 0;11581159/* handle the subexpressions */1160for ( i = 1; i <= len; i++ ) {11611162/* if the subexpression is empty */1163if ( ADDR_EXPR(expr)[i-1] == 0 ) {1164if (!posshole)1165posshole = 1;1166continue;1167}1168else1169{1170if (posshole == 1)1171{1172SET_FILT_LIST(list, FN_IS_NDENSE);1173posshole = 2;1174}11751176/* special case if subexpression is a list expression */1177if ( TNUM_EXPR( ADDR_EXPR(expr)[i-1] ) == T_LIST_EXPR ) {1178sub = ListExpr1( ADDR_EXPR(expr)[i-1] );1179SET_ELM_PLIST( list, i, sub );1180CHANGED_BAG( list );1181ListExpr2( sub, ADDR_EXPR(expr)[i-1] );1182}11831184/* special case if subexpression is a record expression */1185else if ( TNUM_EXPR( ADDR_EXPR(expr)[i-1] ) == T_REC_EXPR ) {1186sub = RecExpr1( ADDR_EXPR(expr)[i-1] );1187SET_ELM_PLIST( list, i, sub );1188CHANGED_BAG( list );1189RecExpr2( sub, ADDR_EXPR(expr)[i-1] );1190}11911192/* general case */1193else {1194sub = EVAL_EXPR( ADDR_EXPR(expr)[i-1] );1195SET_ELM_PLIST( list, i, sub );1196CHANGED_BAG( list );1197}1198}11991200}1201if (!posshole)1202SET_FILT_LIST(list, FN_IS_DENSE);12031204}120512061207/****************************************************************************1208**1209*F EvalRangeExpr(<expr>) . . . . . eval a range expression to a range value1210**1211** 'EvalRangeExpr' evaluates the range expression <expr> to a range value.1212*/1213Obj EvalRangeExpr (1214Expr expr )1215{1216Obj range; /* range, result */1217Obj val; /* subvalue of range */1218Int low; /* low (as C integer) */1219Int inc; /* increment (as C integer) */1220Int high; /* high (as C integer) */12211222/* evaluate the low value */1223val = EVAL_EXPR( ADDR_EXPR(expr)[0] );1224while ( ! IS_INTOBJ(val) ) {1225val = ErrorReturnObj(1226"Range: <first> must be an integer less than 2^%d (not a %s)",1227NR_SMALL_INT_BITS, (Int)TNAM_OBJ(val),1228"you can replace <first> via 'return <first>;'" );1229}1230low = INT_INTOBJ( val );12311232/* evaluate the second value (if present) */1233if ( SIZE_EXPR(expr) == 3*sizeof(Expr) ) {1234val = EVAL_EXPR( ADDR_EXPR(expr)[1] );1235while ( ! IS_INTOBJ(val) || INT_INTOBJ(val) == low ) {1236if ( ! IS_INTOBJ(val) ) {1237val = ErrorReturnObj(1238"Range: <second> must be an integer less than 2^%d (not a %s)",1239NR_SMALL_INT_BITS, (Int)TNAM_OBJ(val),1240"you can replace <second> via 'return <second>;'" );1241}1242else {1243val = ErrorReturnObj(1244"Range: <second> must not be equal to <first> (%d)",1245(Int)low, 0L,1246"you can replace the integer <second> via 'return <second>;'" );1247}1248}1249inc = INT_INTOBJ(val) - low;1250}1251else {1252inc = 1;1253}12541255/* evaluate and check the high value */1256val = EVAL_EXPR( ADDR_EXPR(expr)[ SIZE_EXPR(expr)/sizeof(Expr)-1 ] );1257while ( ! IS_INTOBJ(val) || (INT_INTOBJ(val) - low) % inc != 0 ) {1258if ( ! IS_INTOBJ(val) ) {1259val = ErrorReturnObj(1260"Range: <last> must be an integer less than 2^%d (not a %s)",1261NR_SMALL_INT_BITS, (Int)TNAM_OBJ(val),1262"you can replace <last> via 'return <last>;'" );1263}1264else {1265val = ErrorReturnObj(1266"Range: <last>-<first> (%d) must be divisible by <inc> (%d)",1267(Int)(INT_INTOBJ(val)-low), (Int)inc,1268"you can replace the integer <last> via 'return <last>;'" );1269}1270}1271high = INT_INTOBJ(val);12721273/* if <low> is larger than <high> the range is empty */1274if ( (0 < inc && high < low) || (inc < 0 && low < high) ) {1275range = NEW_PLIST( T_PLIST, 0 );1276SET_LEN_PLIST( range, 0 );1277}12781279/* if <low> is equal to <high> the range is a singleton list */1280else if ( low == high ) {1281range = NEW_PLIST( T_PLIST, 1 );1282SET_LEN_PLIST( range, 1 );1283SET_ELM_PLIST( range, 1, INTOBJ_INT(low) );1284}12851286/* else make the range */1287else {1288/* the length must be a small integer as well */1289if ((high-low) / inc + 1 >= (1L<<NR_SMALL_INT_BITS)) {1290ErrorQuit("Range: the length of a range must be less than 2^%d.",1291NR_SMALL_INT_BITS, 0L);1292}1293if ( 0 < inc )1294range = NEW_RANGE_SSORT();1295else1296range = NEW_RANGE_NSORT();1297SET_LEN_RANGE( range, (high-low) / inc + 1 );1298SET_LOW_RANGE( range, low );1299SET_INC_RANGE( range, inc );1300}13011302/* return the range */1303return range;1304}130513061307/****************************************************************************1308**1309*F EvalStringExpr(<expr>) . . . . eval string expressions to a string value1310**1311** 'EvalStringExpr' evaluates the string expression <expr> to a string1312** value.1313*/1314Obj EvalStringExpr (1315Expr expr )1316{1317Obj string; /* string value, result */1318UInt len; /* size of expression */13191320len = *((UInt *)ADDR_EXPR(expr));1321string = NEW_STRING(len);1322memcpy((void *)ADDR_OBJ(string), (void *)ADDR_EXPR(expr),1323SIZEBAG_STRINGLEN(len) );13241325/* return the string */1326return string;1327}13281329/****************************************************************************1330**1331*F EvalFloatExprLazy(<expr>) . . . . eval float expressions to a float value1332**1333** 'EvalFloatExpr' evaluates the float expression <expr> to a float1334** value.1335*/1336static Obj CONVERT_FLOAT_LITERAL;1337static Obj FLOAT_LITERAL_CACHE;1338static UInt GVAR_FLOAT_LITERAL_CACHE;1339static Obj MAX_FLOAT_LITERAL_CACHE_SIZE;13401341Obj EvalFloatExprLazy (1342Expr expr )1343{1344Obj string; /* string value */1345UInt len; /* size of expression */1346UInt ix;1347Obj cache= 0;1348Obj fl;13491350ix = ((UInt *)ADDR_EXPR(expr))[1];1351if (ix && (!MAX_FLOAT_LITERAL_CACHE_SIZE ||1352MAX_FLOAT_LITERAL_CACHE_SIZE == INTOBJ_INT(0) ||1353ix <= INT_INTOBJ(MAX_FLOAT_LITERAL_CACHE_SIZE))) {1354cache = FLOAT_LITERAL_CACHE;1355if (!cache)1356{1357cache = NEW_PLIST(T_PLIST,ix);1358AssGVar(GVAR_FLOAT_LITERAL_CACHE, cache);1359}1360else1361assert(IS_PLIST(cache));1362GROW_PLIST(cache,ix);1363fl = ELM_PLIST(cache,ix);1364if (fl)1365return fl;1366}1367len = *((UInt *)ADDR_EXPR(expr));1368string = NEW_STRING(len);1369memcpy((void *)CHARS_STRING(string),1370(void *)((char *)ADDR_EXPR(expr) + 2*sizeof(UInt)),1371len );1372fl = CALL_1ARGS(CONVERT_FLOAT_LITERAL, string);1373if (cache) {1374SET_ELM_PLIST(cache, ix, fl);1375CHANGED_BAG(cache);1376if (LEN_PLIST(cache) < ix)1377SET_LEN_PLIST(cache, ix);1378}13791380return fl;1381}13821383/****************************************************************************1384**1385*F EvalFloatExprEager(<expr>) . . . . eval float expressions to a float value1386**1387** 'EvalFloatExpr' evaluates the float expression <expr> to a float1388** value.1389*/1390static Obj EAGER_FLOAT_LITERAL_CACHE;13911392Obj EvalFloatExprEager (1393Expr expr )1394{1395UInt ix;1396Obj cache= 0;1397Obj fl;13981399ix = ((UInt *)ADDR_EXPR(expr))[0];1400cache = EAGER_FLOAT_LITERAL_CACHE;1401assert(IS_PLIST(cache));1402fl = ELM_PLIST(cache,ix);1403assert(fl);1404return fl;1405}140614071408/****************************************************************************1409**1410*F EvalRecExpr(<expr>) . . . . . . eval record expression to a record value1411**1412** 'EvalRecExpr' evaluates the record expression, i.e., not yet evaluated1413** record, <expr> to a record value.1414**1415** 'EvalRecExpr' just calls 'RecExpr1' and 'RecExpr2' to evaluate the record1416** expression.1417*/1418Obj EvalRecExpr (1419Expr expr )1420{1421Obj rec; /* record value, result */14221423/* evaluate the record expression */1424rec = RecExpr1( expr );1425RecExpr2( rec, expr );14261427/* return the result */1428return rec;1429}143014311432/****************************************************************************1433**1434*F EvalRecTildeExpr(<expr>) . . . evaluate a record expression with a tilde1435**1436** 'EvalRecTildeExpr' evaluates the record expression, i.e., not yet1437** evaluated record, <expr> to a record value. The difference to1438** 'EvalRecExpr' is that in <expr> there are occurrences of '~' referring to1439** this record value.1440**1441** 'EvalRecTildeExpr' just calls 'RecExpr1' to create teh record, assigns1442** the record to the variable '~', and finally calls 'RecExpr2' to evaluate1443** the subexpressions into the record. Thus subexpressions in the record1444** expression can refer to this variable and its subobjects to create1445** objects that are not trees.1446*/1447Obj EvalRecTildeExpr (1448Expr expr )1449{1450Obj rec; /* record value, result */1451Obj tilde; /* old value of tilde */14521453/* remember the old value of '~' */1454tilde = VAL_GVAR( Tilde );14551456/* create the record value */1457rec = RecExpr1( expr );14581459/* assign the record value to the variable '~' */1460AssGVar( Tilde, rec );14611462/* evaluate the subexpressions into the record value */1463RecExpr2( rec, expr );14641465/* restore the old value of '~' */1466AssGVar( Tilde, tilde );14671468/* return the record value */1469return rec;1470}147114721473/****************************************************************************1474**1475*F RecExpr1(<expr>) . . . . . . . . . make a record for a record expression1476*F RecExpr2(<rec>,<expr>) . . enter the subobjects for a record expression1477**1478** 'RecExpr1' and 'RecExpr2' together evaluate the record expression <expr>1479** into the record <rec>.1480**1481** 'RecExpr1' allocates a new record of the same size as the record1482** expression <expr> and returns this record.1483**1484** 'RecExpr2' evaluates the subexpressions of <expr> and puts the values1485** into the record <rec> (which should be a record of the same size as the1486** record expression <expr>, e.g., the one allocated by 'RecExpr1').1487**1488** This two step allocation is necessary, because record expressions such as1489** 'rec( a := 1, ~.a )' requires that the value of one subexpression is1490** entered into the record value before the next subexpression is evaluated.1491*/1492Obj RecExpr1 (1493Expr expr )1494{1495Obj rec; /* record value, result */1496Int len; /* number of components */14971498/* get the number of components */1499len = SIZE_EXPR( expr ) / (2*sizeof(Expr));15001501/* allocate the record value */1502rec = NEW_PREC( len );15031504/* return the record */1505return rec;1506}15071508void RecExpr2 (1509Obj rec,1510Expr expr )1511{1512UInt rnam; /* name of component */1513Obj sub; /* value of subexpression */1514Int len; /* number of components */1515Expr tmp; /* temporary variable */1516Int i; /* loop variable */15171518/* get the number of components */1519len = SIZE_EXPR( expr ) / (2*sizeof(Expr));15201521/* handle the subexpressions */1522for ( i = 1; i <= len; i++ ) {15231524/* handle the name */1525tmp = ADDR_EXPR(expr)[2*i-2];1526if ( IS_INTEXPR(tmp) ) {1527rnam = (UInt)INT_INTEXPR(tmp);1528}1529else {1530rnam = RNamObj( EVAL_EXPR(tmp) );1531}15321533/* if the subexpression is empty (cannot happen for records) */1534tmp = ADDR_EXPR(expr)[2*i-1];1535if ( tmp == 0 ) {1536continue;1537}15381539/* special case if subexpression is a list expression */1540else if ( TNUM_EXPR( tmp ) == T_LIST_EXPR ) {1541sub = ListExpr1( tmp );1542AssPRec(rec,rnam,sub);1543ListExpr2( sub, tmp );1544}15451546/* special case if subexpression is a record expression */1547else if ( TNUM_EXPR( tmp ) == T_REC_EXPR ) {1548sub = RecExpr1( tmp );1549AssPRec(rec,rnam,sub);1550RecExpr2( sub, tmp );1551}15521553/* general case */1554else {1555sub = EVAL_EXPR( tmp );1556AssPRec(rec,rnam,sub);1557}1558}1559SortPRecRNam(rec,0);15601561}156215631564/****************************************************************************1565**1566*F PrintExpr(<expr>) . . . . . . . . . . . . . . . . . . print an expression1567**1568** 'PrintExpr' prints the expression <expr>.1569**1570** 'PrintExpr' simply dispatches through the table 'PrintExprFuncs' to the1571** appropriate printer.1572*/1573void PrintExpr (1574Expr expr )1575{1576(*PrintExprFuncs[ TNUM_EXPR(expr) ])( expr );1577}157815791580/****************************************************************************1581**1582*V PrintExprFuncs[<type>] . . printing function for objects of type <type>1583**1584** 'PrintExprFuncs' is the dispatching table that contains for every type of1585** expressions a pointer to the printer for expressions of this type, i.e.,1586** the function that should be called to print expressions of this type.1587*/1588void (* PrintExprFuncs[256] ) ( Expr expr );158915901591/****************************************************************************1592**1593*F PrintUnknownExpr(<expr>) . . . . . . . print expression of unknown type1594**1595** 'PrintUnknownExpr' is the printer that is called if an attempt is made to1596** print an expression <expr> of an unknown type. It signals an error. If1597** this is ever called, then GAP is in serious trouble, such as an1598** overwritten type field of an expression.1599*/1600void PrintUnknownExpr (1601Expr expr )1602{1603Pr( "Panic: tried to print an expression of unknown type '%d'\n",1604(Int)TNUM_EXPR(expr), 0L );1605}160616071608/****************************************************************************1609**1610*V PrintPreceedence . . . . . . . . . . . . . . . current preceedence level1611**1612** 'PrintPreceedence' contains the current preceedence level, i.e. an1613** integer indicating the binding power of the currently printed operator.1614** If one of the operands is an operation that has lower binding power it is1615** printed in parenthesis. If the right operand has the same binding power1616** it is put in parenthesis, since all the operations are left associative.1617** Preceedence: 14: ^; 12: mod,/,*; 10: -,+; 8: in,=; 6: not; 4: and; 2: or.1618** This sometimes puts in superflous parenthesis: 2 * f( (3 + 4) ), since it1619** doesn't know that a function call adds automatically parenthesis.1620*/1621UInt PrintPreceedence;162216231624/****************************************************************************1625**1626*F PrintNot(<expr>) . . . . . . . . . . . . . print a boolean not operator1627**1628** 'PrintNot' print a not operation in the following form: 'not <expr>'.1629*/1630void PrintNot (1631Expr expr )1632{1633UInt oldPrec;16341635oldPrec = PrintPreceedence;1636PrintPreceedence = 6;16371638/* if necessary print the opening parenthesis */1639if ( oldPrec >= PrintPreceedence ) Pr("%>(%>",0L,0L);1640else Pr("%2>",0L,0L);16411642Pr("not%> ",0L,0L);1643PrintExpr( ADDR_EXPR(expr)[0] );1644Pr("%<",0L,0L);16451646/* if necessary print the closing parenthesis */1647if ( oldPrec >= PrintPreceedence ) Pr("%2<)",0L,0L);1648else Pr("%2<",0L,0L);16491650PrintPreceedence = oldPrec;1651}165216531654/****************************************************************************1655**1656*F PrintBinop(<expr>) . . . . . . . . . . . . . . prints a binary operator1657**1658** 'PrintBinop' prints the binary operator expression <expr>, using1659** 'PrintPreceedence' for parenthesising.1660*/1661void PrintAInv (1662Expr expr )1663{1664UInt oldPrec;16651666oldPrec = PrintPreceedence;1667PrintPreceedence = 11;16681669/* if necessary print the opening parenthesis */1670if ( oldPrec >= PrintPreceedence ) Pr("%>(%>",0L,0L);1671else Pr("%2>",0L,0L);16721673Pr("-%> ",0L,0L);1674PrintExpr( ADDR_EXPR(expr)[0] );1675Pr("%<",0L,0L);16761677/* if necessary print the closing parenthesis */1678if ( oldPrec >= PrintPreceedence ) Pr("%2<)",0L,0L);1679else Pr("%2<",0L,0L);16801681PrintPreceedence = oldPrec;1682}16831684void PrintInv (1685Expr expr )1686{1687UInt oldPrec;16881689oldPrec = PrintPreceedence;1690PrintPreceedence = 14;1691Pr("%> ",0L,0L);1692PrintExpr( ADDR_EXPR(expr)[0] );1693Pr("%<^-1",0L,0L);1694PrintPreceedence = oldPrec;1695}16961697void PrintBinop (1698Expr expr )1699{1700UInt oldPrec; /* old preceedence level */1701const Char * op; /* operand */1702/* remember the current preceedence level */1703oldPrec = PrintPreceedence;17041705/* select the new preceedence level */1706switch ( TNUM_EXPR(expr) ) {1707case T_OR: op = "or"; PrintPreceedence = 2; break;1708case T_AND: op = "and"; PrintPreceedence = 4; break;1709case T_EQ: op = "="; PrintPreceedence = 8; break;1710case T_LT: op = "<"; PrintPreceedence = 8; break;1711case T_GT: op = ">"; PrintPreceedence = 8; break;1712case T_NE: op = "<>"; PrintPreceedence = 8; break;1713case T_LE: op = "<="; PrintPreceedence = 8; break;1714case T_GE: op = ">="; PrintPreceedence = 8; break;1715case T_IN: op = "in"; PrintPreceedence = 8; break;1716case T_SUM: op = "+"; PrintPreceedence = 10; break;1717case T_DIFF: op = "-"; PrintPreceedence = 10; break;1718case T_PROD: op = "*"; PrintPreceedence = 12; break;1719case T_QUO: op = "/"; PrintPreceedence = 12; break;1720case T_MOD: op = "mod"; PrintPreceedence = 12; break;1721case T_POW: op = "^"; PrintPreceedence = 16; break;1722default: op = "<bogus-operator>"; break;1723}17241725/* if necessary print the opening parenthesis */1726if ( oldPrec > PrintPreceedence ) Pr("%>(%>",0L,0L);1727else Pr("%2>",0L,0L);17281729/* print the left operand */1730if ( TNUM_EXPR(expr) == T_POW1731&& (( (IS_INTEXPR(ADDR_EXPR(expr)[0])1732&& INT_INTEXPR(ADDR_EXPR(expr)[0]) < 0)1733|| TNUM_EXPR(ADDR_EXPR(expr)[0]) == T_INTNEG)1734|| TNUM_EXPR(ADDR_EXPR(expr)[0]) == T_POW) ) {1735Pr( "(", 0L, 0L );1736PrintExpr( ADDR_EXPR(expr)[0] );1737Pr( ")", 0L, 0L );1738}1739else {1740PrintExpr( ADDR_EXPR(expr)[0] );1741}17421743/* print the operator */1744Pr("%2< %2>%s%> %<",(Int)op,0L);17451746/* print the right operand */1747PrintPreceedence++;1748PrintExpr( ADDR_EXPR(expr)[1] );1749PrintPreceedence--;17501751/* if necessary print the closing parenthesis */1752if ( oldPrec > PrintPreceedence ) Pr("%2<)",0L,0L);1753else Pr("%2<",0L,0L);17541755/* restore the old preceedence level */1756PrintPreceedence = oldPrec;1757}175817591760/****************************************************************************1761**1762*F PrintIntExpr(<expr>) . . . . . . . . . . . . print an integer expression1763**1764** 'PrintIntExpr' prints the literal integer expression <expr>.1765*/1766void PrintIntExpr (1767Expr expr )1768{1769if ( IS_INTEXPR(expr) ) {1770Pr( "%d", INT_INTEXPR(expr), 0L );1771}1772else {1773PrintInt(EvalIntExpr(expr));1774}1775}177617771778/****************************************************************************1779**1780*F PrintTrueExpr(<expr>) . . . . . . . . . . . print literal true expression1781*/1782void PrintTrueExpr (1783Expr expr )1784{1785Pr( "true", 0L, 0L );1786}178717881789/****************************************************************************1790**1791*F PrintFalseExpr(<expr>) . . . . . . . . . print literal false expression1792*/1793void PrintFalseExpr (1794Expr expr )1795{1796Pr( "false", 0L, 0L );1797}179817991800/****************************************************************************1801**1802*F PrintCharExpr(<expr>) . . . . . . . . print literal character expression1803*/1804void PrintCharExpr (1805Expr expr )1806{1807UChar chr;18081809chr = *(UChar*)ADDR_EXPR(expr);1810if ( chr == '\n' ) Pr("'\\n'",0L,0L);1811else if ( chr == '\t' ) Pr("'\\t'",0L,0L);1812else if ( chr == '\r' ) Pr("'\\r'",0L,0L);1813else if ( chr == '\b' ) Pr("'\\b'",0L,0L);1814else if ( chr == '\03' ) Pr("'\\c'",0L,0L);1815else if ( chr == '\'' ) Pr("'\\''",0L,0L);1816else if ( chr == '\\' ) Pr("'\\\\'",0L,0L);1817else Pr("'%c'",(Int)chr,0L);1818}181918201821/****************************************************************************1822**1823*F PrintPermExpr(<expr>) . . . . . . . . . . print a permutation expression1824**1825** 'PrintPermExpr' prints the permutation expression <expr>.1826*/1827void PrintPermExpr (1828Expr expr )1829{1830Expr cycle; /* one cycle of permutation expr. */1831UInt i, j; /* loop variables */18321833/* if there are no cycles, print the identity permutation */1834if ( SIZE_EXPR(expr) == 0 ) {1835Pr("()",0L,0L);1836}18371838/* print all cycles */1839for ( i = 1; i <= SIZE_EXPR(expr)/sizeof(Expr); i++ ) {1840cycle = ADDR_EXPR(expr)[i-1];1841Pr("%>(",0L,0L);18421843/* print all entries of that cycle */1844for ( j = 1; j <= SIZE_EXPR(cycle)/sizeof(Expr); j++ ) {1845Pr("%>",0L,0L);1846PrintExpr( ADDR_EXPR(cycle)[j-1] );1847Pr("%<",0L,0L);1848if ( j < SIZE_EXPR(cycle)/sizeof(Expr) ) Pr(",",0L,0L);1849}18501851Pr("%<)",0L,0L);1852}1853}185418551856/****************************************************************************1857**1858*F PrintListExpr(<expr>) . . . . . . . . . . . . . . print a list expression1859**1860** 'PrintListExpr' prints the list expression <expr>.1861*/1862void PrintListExpr (1863Expr expr )1864{1865Int len; /* logical length of <list> */1866Expr elm; /* one element from <list> */1867Int i; /* loop variable */18681869/* get the logical length of the list */1870len = SIZE_EXPR( expr ) / sizeof(Expr);18711872/* loop over the entries */1873Pr("%2>[ %2>",0L,0L);1874for ( i = 1; i <= len; i++ ) {1875elm = ADDR_EXPR(expr)[i-1];1876if ( elm != 0 ) {1877if ( 1 < i ) Pr("%<,%< %2>",0L,0L);1878PrintExpr( elm );1879}1880else {1881if ( 1 < i ) Pr("%2<,%2>",0L,0L);1882}1883}1884Pr(" %4<]",0L,0L);1885}188618871888/****************************************************************************1889**1890*F PrintRangeExpr(<expr>) . . . . . . . . . . . . . print range expression1891**1892** 'PrintRangeExpr' prints the record expression <expr>.1893*/1894void PrintRangeExpr (1895Expr expr )1896{1897if ( SIZE_EXPR( expr ) == 2*sizeof(Expr) ) {1898Pr("%2>[ %2>",0L,0L); PrintExpr( ADDR_EXPR(expr)[0] );1899Pr("%2< .. %2>",0L,0L); PrintExpr( ADDR_EXPR(expr)[1] );1900Pr(" %4<]",0L,0L);1901}1902else {1903Pr("%2>[ %2>",0L,0L); PrintExpr( ADDR_EXPR(expr)[0] );1904Pr("%<,%< %2>",0L,0L); PrintExpr( ADDR_EXPR(expr)[1] );1905Pr("%2< .. %2>",0L,0L); PrintExpr( ADDR_EXPR(expr)[2] );1906Pr(" %4<]",0L,0L);1907}1908}190919101911/****************************************************************************1912**1913*F PrintStringExpr(<expr>) . . . . . . . . . . . . print a string expression1914**1915** 'PrintStringExpr' prints the string expression <expr>.1916*/1917void PrintStringExpr (1918Expr expr )1919{1920PrintString(EvalStringExpr(expr));1921/*Pr( "\"%S\"", (Int)ADDR_EXPR(expr), 0L );*/1922}19231924/****************************************************************************1925**1926*F PrintFloatExpr(<expr>) . . . . . . . . . . . . print a float expression1927**1928** 'PrintFloatExpr' prints the float expression <expr>.1929*/1930void PrintFloatExprLazy (1931Expr expr )1932{1933Pr("%s", (Int)(((char *)ADDR_EXPR(expr) + 2*sizeof(UInt))), 0L);1934}19351936/****************************************************************************1937**1938*F PrintFloatExprEager(<expr>) . . . . . . . . . . . . print a float expression1939**1940** 'PrintFloatExpr' prints the float expression <expr>.1941*/1942void PrintFloatExprEager (1943Expr expr )1944{1945Char mark;1946Pr("%s", (Int)(((char *)ADDR_EXPR(expr) + 3*sizeof(UInt))), 0L);1947Pr("_",0L,0L);1948mark = (Char)(((UInt *)ADDR_EXPR(expr))[2]);1949if (mark != '\0') {1950Pr("%c",mark,0L);1951}1952}195319541955/****************************************************************************1956**1957*F PrintRecExpr(<expr>) . . . . . . . . . . . . . print a record expression1958**1959** 'PrintRecExpr' the record expression <expr>.1960*/1961void PrintRecExpr1 (1962Expr expr )1963{1964Expr tmp; /* temporary variable */1965UInt i; /* loop variable */19661967for ( i = 1; i <= SIZE_EXPR(expr)/(2*sizeof(Expr)); i++ ) {1968/* print an ordinary record name */1969tmp = ADDR_EXPR(expr)[2*i-2];1970if ( IS_INTEXPR(tmp) ) {1971Pr( "%I", (Int)NAME_RNAM( INT_INTEXPR(tmp) ), 0L );1972}19731974/* print an evaluating record name */1975else {1976Pr(" (",0L,0L);1977PrintExpr( tmp );1978Pr(")",0L,0L);1979}19801981/* print the component */1982tmp = ADDR_EXPR(expr)[2*i-1];1983Pr("%< := %>",0L,0L);1984PrintExpr( tmp );1985if ( i < SIZE_EXPR(expr)/(2*sizeof(Expr)) )1986Pr("%2<,\n%2>",0L,0L);19871988}1989}19901991void PrintRecExpr (1992Expr expr )1993{1994Pr("%2>rec(\n%2>",0L,0L);1995PrintRecExpr1(expr);1996Pr(" %4<)",0L,0L);19971998}199920002001/****************************************************************************2002**20032004*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *2005*/200620072008/****************************************************************************2009**20102011*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures2012*/2013static Int InitKernel (2014StructInitInfo * module )2015{2016UInt type; /* loop variable */20172018InitFopyGVar("CONVERT_FLOAT_LITERAL",&CONVERT_FLOAT_LITERAL);2019InitCopyGVar("FLOAT_LITERAL_CACHE",&FLOAT_LITERAL_CACHE);2020InitCopyGVar("EAGER_FLOAT_LITERAL_CACHE",&EAGER_FLOAT_LITERAL_CACHE);2021InitCopyGVar("MAX_FLOAT_LITERAL_CACHE_SIZE",&MAX_FLOAT_LITERAL_CACHE_SIZE);202220232024/* clear the evaluation dispatch table */2025for ( type = 0; type < 256; type++ ) {2026InstallEvalExprFunc( type , EvalUnknownExpr);2027InstallEvalBoolFunc( type , EvalUnknownBool);2028}20292030/* install the evaluators for logical operations */2031InstallEvalExprFunc( T_OR , EvalOr);2032InstallEvalExprFunc( T_AND , EvalAnd);2033InstallEvalExprFunc( T_NOT , EvalNot);20342035/* the logical operations are guaranteed to return booleans */2036InstallEvalBoolFunc( T_OR , EvalOr);2037InstallEvalBoolFunc( T_AND , EvalAnd);2038InstallEvalBoolFunc( T_NOT , EvalNot);20392040/* install the evaluators for comparison operations */2041InstallEvalExprFunc( T_EQ , EvalEq);2042InstallEvalExprFunc( T_NE , EvalNe);2043InstallEvalExprFunc( T_LT , EvalLt);2044InstallEvalExprFunc( T_GE , EvalGe);2045InstallEvalExprFunc( T_GT , EvalGt);2046InstallEvalExprFunc( T_LE , EvalLe);2047InstallEvalExprFunc( T_IN , EvalIn);20482049/* the comparison operations are guaranteed to return booleans */2050InstallEvalBoolFunc( T_EQ , EvalEq);2051InstallEvalBoolFunc( T_NE , EvalNe);2052InstallEvalBoolFunc( T_LT , EvalLt);2053InstallEvalBoolFunc( T_GE , EvalGe);2054InstallEvalBoolFunc( T_GT , EvalGt);2055InstallEvalBoolFunc( T_LE , EvalLe);2056InstallEvalBoolFunc( T_IN , EvalIn);20572058/* install the evaluators for binary operations */2059InstallEvalExprFunc( T_SUM , EvalSum);2060InstallEvalExprFunc( T_AINV , EvalAInv);2061InstallEvalExprFunc( T_DIFF , EvalDiff);2062InstallEvalExprFunc( T_PROD , EvalProd);2063InstallEvalExprFunc( T_INV , EvalInv);2064InstallEvalExprFunc( T_QUO , EvalQuo);2065InstallEvalExprFunc( T_MOD , EvalMod);2066InstallEvalExprFunc( T_POW , EvalPow);20672068/* install the evaluators for literal expressions */2069InstallEvalExprFunc( T_INT_EXPR , EvalIntExpr);2070InstallEvalExprFunc( T_TRUE_EXPR , EvalTrueExpr);2071InstallEvalExprFunc( T_FALSE_EXPR , EvalFalseExpr);2072InstallEvalExprFunc( T_CHAR_EXPR , EvalCharExpr);2073InstallEvalExprFunc( T_PERM_EXPR , EvalPermExpr);20742075/* install the evaluators for list and record expressions */2076InstallEvalExprFunc( T_LIST_EXPR , EvalListExpr);2077InstallEvalExprFunc( T_LIST_TILD_EXPR , EvalListTildeExpr);2078InstallEvalExprFunc( T_RANGE_EXPR , EvalRangeExpr);2079InstallEvalExprFunc( T_STRING_EXPR , EvalStringExpr);2080InstallEvalExprFunc( T_REC_EXPR , EvalRecExpr);2081InstallEvalExprFunc( T_REC_TILD_EXPR , EvalRecTildeExpr);2082InstallEvalExprFunc( T_FLOAT_EXPR_LAZY , EvalFloatExprLazy);2083InstallEvalExprFunc( T_FLOAT_EXPR_EAGER , EvalFloatExprEager);20842085/* clear the tables for the printing dispatching */2086for ( type = 0; type < 256; type++ ) {2087InstallPrintExprFunc( type , PrintUnknownExpr);2088}20892090/* install the printers for logical operations */2091InstallPrintExprFunc( T_OR , PrintBinop);2092InstallPrintExprFunc( T_AND , PrintBinop);2093InstallPrintExprFunc( T_NOT , PrintNot);20942095/* install the printers for comparison operations */2096InstallPrintExprFunc( T_EQ , PrintBinop);2097InstallPrintExprFunc( T_LT , PrintBinop);2098InstallPrintExprFunc( T_NE , PrintBinop);2099InstallPrintExprFunc( T_GE , PrintBinop);2100InstallPrintExprFunc( T_GT , PrintBinop);2101InstallPrintExprFunc( T_LE , PrintBinop);2102InstallPrintExprFunc( T_IN , PrintBinop);21032104/* install the printers for binary operations */2105InstallPrintExprFunc( T_SUM , PrintBinop);2106InstallPrintExprFunc( T_AINV , PrintAInv);2107InstallPrintExprFunc( T_DIFF , PrintBinop);2108InstallPrintExprFunc( T_PROD , PrintBinop);2109InstallPrintExprFunc( T_INV , PrintInv);2110InstallPrintExprFunc( T_QUO , PrintBinop);2111InstallPrintExprFunc( T_MOD , PrintBinop);2112InstallPrintExprFunc( T_POW , PrintBinop);21132114/* install the printers for literal expressions */2115InstallPrintExprFunc( T_INTEXPR , PrintIntExpr);2116InstallPrintExprFunc( T_INT_EXPR , PrintIntExpr);2117InstallPrintExprFunc( T_TRUE_EXPR , PrintTrueExpr);2118InstallPrintExprFunc( T_FALSE_EXPR , PrintFalseExpr);2119InstallPrintExprFunc( T_CHAR_EXPR , PrintCharExpr);2120InstallPrintExprFunc( T_PERM_EXPR , PrintPermExpr);21212122/* install the printers for list and record expressions */2123InstallPrintExprFunc( T_LIST_EXPR , PrintListExpr);2124InstallPrintExprFunc( T_LIST_TILD_EXPR , PrintListExpr);2125InstallPrintExprFunc( T_RANGE_EXPR , PrintRangeExpr);2126InstallPrintExprFunc( T_STRING_EXPR , PrintStringExpr);2127InstallPrintExprFunc( T_FLOAT_EXPR_LAZY , PrintFloatExprLazy);2128InstallPrintExprFunc( T_FLOAT_EXPR_EAGER , PrintFloatExprEager);2129InstallPrintExprFunc( T_REC_EXPR , PrintRecExpr);2130InstallPrintExprFunc( T_REC_TILD_EXPR , PrintRecExpr);21312132/* return success */2133return 0;2134}213521362137static Int InitLibrary (2138StructInitInfo * module )2139{2140GVAR_FLOAT_LITERAL_CACHE = GVarName("FLOAT_LITERAL_CACHE");2141return 0;2142}21432144/****************************************************************************2145**2146*F InitInfoExprs() . . . . . . . . . . . . . . . . . table of init functions2147*/2148static StructInitInfo module = {2149MODULE_BUILTIN, /* type */2150"exprs", /* name */21510, /* revision entry of c file */21520, /* revision entry of h file */21530, /* version */21540, /* crc */2155InitKernel, /* initKernel */2156InitLibrary, /* initLibrary */21570, /* checkInit */21580, /* preSave */21590, /* postSave */2160InitLibrary /* postRestore */2161};21622163StructInitInfo * InitInfoExprs ( void )2164{2165return &module;2166}216721682169/****************************************************************************2170**21712172*E exprs.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here2173*/217421752176