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 code.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 coder package.10**11** The coder package is the part of the interpreter that creates the12** expressions. Its functions are called from the reader.13*/14#include <stdio.h> /* on SunOS, assert.h uses stderr15but does not include stdio.h */16#include <assert.h> /* assert */17#include "system.h" /* Ints, UInts */181920#include "gasman.h" /* garbage collector */21#include "objects.h" /* objects */22#include "scanner.h" /* scanner */2324#include "gap.h" /* error handling, initialisation */2526#include "calls.h" /* generic call mechanism */27/*N 1996/06/16 mschoene func expressions should be different from funcs */2829#include "records.h" /* generic records */3031#include "integer.h" /* integers */3233#include "records.h" /* generic records */34#include "precord.h" /* plain records */3536#include "lists.h" /* generic lists */37#include "plist.h" /* plain lists */38#include "string.h" /* strings */3940#include "funcs.h" /* functions */4142#include "code.h" /* coder */4344#include "saveload.h" /* saving and loading */45#include "read.h" /* to access stack of for loop globals */46#include "gvars.h"47#include "thread.h" /* threads */48#include "tls.h" /* thread-local storage */49#include "aobjects.h" /* atomic objects */5051#include "vars.h" /* variables */525354#include "profile.h" /* access to stat register function*/5556/****************************************************************************57**5859*V PtrBody . . . . . . . . . . . . . . . . . . . . . pointer to current body60**61** 'PtrBody' is a pointer to the current body.62*/63Stat * PtrBody;6465/****************************************************************************66**6768*V FilenameCache . . . . . . . . . . . . . . . . . . list of filenames69**70** 'FilenameCache' is a list of previously opened filenames.71*/72Obj FilenameCache;7374/****************************************************************************75**76*V OffsBody . . . . . . . . . . . . . . . . . . . . offset in current body77**78** 'OffsBody' is the offset in the current body. It is only valid while79** coding.80*/81#define MAX_FUNC_EXPR_NESTING 1024828384Stat OffsBody;8586Stat OffsBodyStack[MAX_FUNC_EXPR_NESTING];87UInt OffsBodyCount = 0;8889UInt LoopNesting = 0;90UInt LoopStack[MAX_FUNC_EXPR_NESTING];91UInt LoopStackCount = 0;9293static inline void PushOffsBody( void ) {94assert(TLS(OffsBodyCount) <= MAX_FUNC_EXPR_NESTING-1);95TLS(OffsBodyStack)[TLS(OffsBodyCount)++] = TLS(OffsBody);96}9798static inline void PopOffsBody( void ) {99assert(TLS(OffsBodyCount));100TLS(OffsBody) = TLS(OffsBodyStack)[--TLS(OffsBodyCount)];101}102103static inline void PushLoopNesting( void ) {104assert(TLS(LoopStackCount) <= MAX_FUNC_EXPR_NESTING-1);105TLS(LoopStack)[TLS(LoopStackCount)++] = TLS(LoopNesting);106}107108static inline void PopLoopNesting( void ) {109assert(TLS(LoopStackCount));110TLS(LoopNesting) = TLS(LoopStack)[--TLS(LoopStackCount)];111}112113static inline void setup_gapname(TypInputFile* i)114{115UInt len;116if(!i->gapname) {117C_NEW_STRING_DYN(i->gapname, i->name);118len = LEN_PLIST( FilenameCache );119GROW_PLIST( FilenameCache, len+1 );120SET_LEN_PLIST( FilenameCache, len+1 );121SET_ELM_PLIST( FilenameCache, len+1, i->gapname );122CHANGED_BAG( FilenameCache );123i->gapnameid = len+1;124}125}126127Obj FILENAME_STAT(Stat stat)128{129Obj filename;130UInt filenameid = FILENAMEID_STAT(stat);131if (filenameid == 0)132filename = NEW_STRING(0);133else134filename = ELM_PLIST(FilenameCache, filenameid);135return filename;136}137138139/****************************************************************************140**141** Fill in filename and line of a statement, checking we do not overflow142** the space we have for storing information143*/144Stat fillFilenameLine(Int fileid, Int line, Int size, Int type)145{146Stat stat;147if(fileid < 0 || fileid >= (1 << 16))148{149fileid = (1 << 16) - 1;150RegisterProfilingFileOverflowOccured();151}152if(line < 0 || line >= (1 << 16))153{154line = (1 << 16) - 1;155RegisterProfilingLineOverflowOccured();156}157158stat = ((Stat)fileid << 48) + ((Stat)line << 32) +159((Stat)size << 8) + (Stat)type;160161return stat;162}163164/****************************************************************************165**166*F NewStat( <type>, <size> ) . . . . . . . . . . . allocate a new statement167**168** 'NewStat' allocates a new statement memory block of type <type> and169** <size> bytes. 'NewStat' returns the identifier of the new statement.170**171** NewStat( <type>, <size>, <line> ) allows the line number of the statement172** to also be specified (else the current line when NewStat is called is173** used).174*/175Stat NewStatWithLine (176UInt type,177UInt size,178UInt line)179{180Stat stat; /* result */181182/* this is where the new statement goes */183stat = TLS(OffsBody) + FIRST_STAT_CURR_FUNC;184185/* increase the offset */186TLS(OffsBody) = stat + ((size+sizeof(Stat)-1) / sizeof(Stat)) * sizeof(Stat);187188/* make certain that the current body bag is large enough */189if ( SIZE_BAG(BODY_FUNC(CURR_FUNC)) == 0 ) {190ResizeBag( BODY_FUNC(CURR_FUNC), TLS(OffsBody) + NUMBER_HEADER_ITEMS_BODY*sizeof(Obj) );191TLS(PtrBody) = (Stat*)PTR_BAG( BODY_FUNC(CURR_FUNC) );192}193while ( SIZE_BAG(BODY_FUNC(CURR_FUNC)) < TLS(OffsBody) + NUMBER_HEADER_ITEMS_BODY*sizeof(Obj) ) {194ResizeBag( BODY_FUNC(CURR_FUNC), 2*SIZE_BAG(BODY_FUNC(CURR_FUNC)) );195TLS(PtrBody) = (Stat*)PTR_BAG( BODY_FUNC(CURR_FUNC) );196}197setup_gapname(TLS(Input));198199/* enter type and size */200ADDR_STAT(stat)[-1] = fillFilenameLine(TLS(Input)->gapnameid, line, size, type);201RegisterStatWithProfiling(stat);202/* return the new statement */203return stat;204}205206Stat NewStat (207UInt type,208UInt size)209{210return NewStatWithLine(type, size, TLS(Input)->number);211}212213214/****************************************************************************215**216*F NewExpr( <type>, <size> ) . . . . . . . . . . . allocate a new expression217**218** 'NewExpr' allocates a new expression memory block of the type <type> and219** <size> bytes. 'NewExpr' returns the identifier of the new expression.220*/221Expr NewExpr (222UInt type,223UInt size )224{225Expr expr; /* result */226227/* this is where the new expression goes */228expr = TLS(OffsBody) + FIRST_STAT_CURR_FUNC;229230/* increase the offset */231TLS(OffsBody) = expr + ((size+sizeof(Expr)-1) / sizeof(Expr)) * sizeof(Expr);232233/* make certain that the current body bag is large enough */234if ( SIZE_BAG(BODY_FUNC(CURR_FUNC)) == 0 ) {235ResizeBag( BODY_FUNC(CURR_FUNC), TLS(OffsBody) );236TLS(PtrBody) = (Stat*)PTR_BAG( BODY_FUNC(CURR_FUNC) );237}238while ( SIZE_BAG(BODY_FUNC(CURR_FUNC)) < TLS(OffsBody) ) {239ResizeBag( BODY_FUNC(CURR_FUNC), 2*SIZE_BAG(BODY_FUNC(CURR_FUNC)) );240TLS(PtrBody) = (Stat*)PTR_BAG( BODY_FUNC(CURR_FUNC) );241}242243/* enter type and size */244ADDR_EXPR(expr)[-1] = fillFilenameLine(TLS(Input)->gapnameid,245TLS(Input)->number, size, type);246RegisterStatWithProfiling(expr);247/* return the new expression */248return expr;249}250251252/****************************************************************************253**254*V CodeResult . . . . . . . . . . . . . . . . . . . . . . result of coding255**256** 'CodeResult' is the result of the coding, i.e., the function that was257** coded.258*/259Obj CodeResult;260261262/****************************************************************************263**264*V StackStat . . . . . . . . . . . . . . . . . . . . . . . statements stack265*V CountStat . . . . . . . . . . . . . . . number of statements on the stack266*F PushStat( <stat> ) . . . . . . . . . . . . push statement onto the stack267*F PopStat() . . . . . . . . . . . . . . . . . pop statement from the stack268**269** 'StackStat' is the stack of statements that have been coded.270**271** 'CountStat' is the number of statements currently on the statements272** stack.273**274** 'PushStat' pushes the statement <stat> onto the statements stack. The275** stack is automatically resized if necessary.276**277** 'PopStat' returns the top statement from the statements stack and pops278** it. It is an error if the stack is empty.279*/280Bag StackStat;281282Int CountStat;283284void PushStat (285Stat stat )286{287/* there must be a stack, it must not be underfull or overfull */288assert( TLS(StackStat) != 0 );289assert( 0 <= TLS(CountStat) );290assert( TLS(CountStat) <= SIZE_BAG(TLS(StackStat))/sizeof(Stat) );291assert( stat != 0 );292293/* count up and put the statement onto the stack */294if ( TLS(CountStat) == SIZE_BAG(TLS(StackStat))/sizeof(Stat) ) {295ResizeBag( TLS(StackStat), 2*TLS(CountStat)*sizeof(Stat) );296}297((Stat*)PTR_BAG(TLS(StackStat)))[TLS(CountStat)] = stat;298TLS(CountStat)++;299}300301Stat PopStat ( void )302{303Stat stat;304305/* there must be a stack, it must not be underfull/empty or overfull */306assert( TLS(StackStat) != 0 );307assert( 1 <= TLS(CountStat) );308assert( TLS(CountStat) <= SIZE_BAG(TLS(StackStat))/sizeof(Stat) );309310/* get the top statement from the stack, and count down */311TLS(CountStat)--;312stat = ((Stat*)PTR_BAG(TLS(StackStat)))[TLS(CountStat)];313314/* return the popped statement */315return stat;316}317318Stat PopSeqStat (319UInt nr )320{321Stat body; /* sequence, result */322Stat stat; /* single statement */323UInt i; /* loop variable */324325if (nr == 0 ) {326body = NewStat(T_EMPTY, 0);327}328/* special case for a single statement */329else if ( nr == 1 ) {330body = PopStat();331}332333/* general case */334else {335336/* allocate the sequence */337if ( 2 <= nr && nr <= 7 ) {338body = NewStat( T_SEQ_STAT+(nr-1), nr * sizeof(Stat) );339}340else {341body = NewStat( T_SEQ_STAT, nr * sizeof(Stat) );342}343344/* enter the statements into the sequence */345for ( i = nr; 1 <= i; i-- ) {346stat = PopStat();347ADDR_STAT(body)[i-1] = stat;348}349}350351/* return the sequence */352return body;353}354355356/****************************************************************************357**358*V StackExpr . . . . . . . . . . . . . . . . . . . . . . . expressions stack359*V CountExpr . . . . . . . . . . . . . . number of expressions on the stack360*F PushExpr( <expr> ) . . . . . . . . . . . push expression onto the stack361*F PopExpr() . . . . . . . . . . . . . . . . pop expression from the stack362**363** 'StackExpr' is the stack of expressions that have been coded.364**365** 'CountExpr' is the number of expressions currently on the expressions366** stack.367**368** 'PushExpr' pushes the expression <expr> onto the expressions stack. The369** stack is automatically resized if necessary.370**371** 'PopExpr' returns the top expressions from the expressions stack and pops372** it. It is an error if the stack is empty.373*/374Bag StackExpr;375376Int CountExpr;377378void PushExpr (379Expr expr )380{381/* there must be a stack, it must not be underfull or overfull */382assert( TLS(StackExpr) != 0 );383assert( 0 <= TLS(CountExpr) );384assert( TLS(CountExpr) <= SIZE_BAG(TLS(StackExpr))/sizeof(Expr) );385assert( expr != 0 );386387/* count up and put the expression onto the stack */388if ( TLS(CountExpr) == SIZE_BAG(TLS(StackExpr))/sizeof(Expr) ) {389ResizeBag( TLS(StackExpr), 2*TLS(CountExpr)*sizeof(Expr) );390}391((Expr*)PTR_BAG(TLS(StackExpr)))[TLS(CountExpr)] = expr;392TLS(CountExpr)++;393}394395Expr PopExpr ( void )396{397Expr expr;398399/* there must be a stack, it must not be underfull/empty or overfull */400assert( TLS(StackExpr) != 0 );401assert( 1 <= TLS(CountExpr) );402assert( TLS(CountExpr) <= SIZE_BAG(TLS(StackExpr))/sizeof(Expr) );403404/* get the top expression from the stack, and count down */405TLS(CountExpr)--;406expr = ((Expr*)PTR_BAG(TLS(StackExpr)))[TLS(CountExpr)];407408/* return the popped expression */409return expr;410}411412413/****************************************************************************414**415*F PushUnaryOp( <type> ) . . . . . . . . . . . . . . . . push unary operator416**417** 'PushUnaryOp' pushes a unary operator expression onto the expression418** stack. <type> is the type of the operator (currently only 'T_NOT').419*/420void PushUnaryOp (421UInt type )422{423Expr unop; /* unary operator, result */424Expr op; /* operand */425426/* allocate the unary operator */427unop = NewExpr( type, sizeof(Expr) );428429/* enter the operand */430op = PopExpr();431ADDR_EXPR(unop)[0] = op;432433/* push the unary operator */434PushExpr( unop );435}436437438/****************************************************************************439**440*F PushBinaryOp( <type> ) . . . . . . . . . . . . . . push binary operator441**442** 'PushBinaryOp' pushes a binary operator expression onto the expression443** stack. <type> is the type of the operator.444*/445void PushBinaryOp (446UInt type )447{448Expr binop; /* binary operator, result */449Expr opL; /* left operand */450Expr opR; /* right operand */451452/* allocate the binary operator */453binop = NewExpr( type, 2*sizeof(Expr) );454455/* enter the right operand */456opR = PopExpr();457ADDR_EXPR(binop)[1] = opR;458459/* enter the left operand */460opL = PopExpr();461ADDR_EXPR(binop)[0] = opL;462463/* push the binary operator */464PushExpr( binop );465}466467468/****************************************************************************469**470471*F * * * * * * * * * * * * * coder functions * * * * * * * * * * * * * * * *472*/473474/****************************************************************************475**476*F CodeFuncCallOptionsBegin() . . . . . . . . . . . . . code options, begin477*F CodeFuncCallOptionsBeginElmName(<rnam>). . . code options, begin element478*F CodeFuncCallOptionsBeginElmExpr() . .. . . . .code options, begin element479*F CodeFuncCallOptionsEndElm() . . .. . . . . . . code options, end element480*F CodeFuncCallOptionsEndElmEmpty() .. . . . . . .code options, end element481*F CodeFuncCallOptionsEnd(<nr>) . . . . . . . . . . . . . code options, end482**483** The net effect of all of these is to leave a record expression on the stack484** containing the options record. It will be picked up by485** CodeFuncCallEnd()486**487*/488void CodeFuncCallOptionsBegin ( void )489{490}491492void CodeFuncCallOptionsBeginElmName (493UInt rnam )494{495/* push the record name as integer expressions */496PushExpr( INTEXPR_INT( rnam ) );497}498499void CodeFuncCallOptionsBeginElmExpr ( void )500{501/* The expression is on the stack where we want it */502}503504void CodeFuncCallOptionsEndElm ( void )505{506}507508void CodeFuncCallOptionsEndElmEmpty ( void )509{510/* The default value is true */511PushExpr( NewExpr( T_TRUE_EXPR, 0L ) );512}513514void CodeFuncCallOptionsEnd ( UInt nr )515{516Expr record; /* record, result */517Expr entry; /* entry */518Expr rnam; /* position of an entry */519UInt i; /* loop variable */520521/* allocate the record expression */522record = NewExpr( T_REC_EXPR, nr * 2 * sizeof(Expr) );523524525/* enter the entries */526for ( i = nr; 1 <= i; i-- ) {527entry = PopExpr();528rnam = PopExpr();529ADDR_EXPR(record)[2*(i-1)] = rnam;530ADDR_EXPR(record)[2*(i-1)+1] = entry;531}532533/* push the record */534PushExpr( record );535536}537538539/****************************************************************************540**541542*F CodeBegin() . . . . . . . . . . . . . . . . . . . . . . . start the coder543*F CodeEnd( <error> ) . . . . . . . . . . . . . . . . . . . stop the coder544**545** 'CodeBegin' starts the coder. It is called from the immediate546** interpreter when he encounters a construct that it cannot immediately547** interpret.548**549** 'CodeEnd' stops the coder. It is called from the immediate interpreter550** when he is done with the construct that it cannot immediately interpret.551** If <error> is non-zero, a syntax error was detected by the reader, and552** the coder should only clean up.553**554** ...only function expressions inbetween...555*/556Bag CodeLVars;557558void CodeBegin ( void )559{560/* the stacks must be empty */561assert( TLS(CountStat) == 0 );562assert( TLS(CountExpr) == 0 );563564/* remember the current frame */565TLS(CodeLVars) = TLS(CurrLVars);566567/* clear the code result bag */568TLS(CodeResult) = 0;569}570571UInt CodeEnd (572UInt error )573{574/* if everything went fine */575if ( ! error ) {576577/* the stacks must be empty */578assert( TLS(CountStat) == 0 );579assert( TLS(CountExpr) == 0 );580581/* we must be back to 'TLS(CurrLVars)' */582assert( TLS(CurrLVars) == TLS(CodeLVars) );583584/* 'CodeFuncExprEnd' left the function already in 'TLS(CodeResult)' */585}586587/* otherwise clean up the mess */588else {589590/* empty the stacks */591TLS(CountStat) = 0;592TLS(CountExpr) = 0;593594/* go back to the correct frame */595SWITCH_TO_OLD_LVARS( TLS(CodeLVars) );596}597598/* return value is ignored */599return 0;600}601602603/****************************************************************************604**605*F CodeFuncCallBegin() . . . . . . . . . . . . . . code function call, begin606*F CodeFuncCallEnd( <funccall>, <options>, <nr> ) code function call, end607**608** 'CodeFuncCallBegin' is an action to code a function call. It is called609** by the reader when it encounters the parenthesis '(', i.e., *after* the610** function expression is read.611**612** 'CodeFuncCallEnd' is an action to code a function call. It is called by613** the reader when it encounters the parenthesis ')', i.e., *after* the614** argument expressions are read. <funccall> is 1 if this is a function615** call, and 0 if this is a procedure call. <nr> is the number of616** arguments. <options> is 1 if options were present after the ':' in which617** case the options have been read already.618*/619void CodeFuncCallBegin ( void )620{621}622623void CodeFuncCallEnd (624UInt funccall,625UInt options,626UInt nr )627{628Expr call; /* function call, result */629Expr func; /* function expression */630Expr arg; /* one argument expression */631UInt i; /* loop variable */632Expr opts = 0; /* record literal for the options */633Expr wrapper; /* wrapper for calls with options */634635/* allocate the function call */636if ( funccall && nr <= 6 ) {637call = NewExpr( T_FUNCCALL_0ARGS+nr, SIZE_NARG_CALL(nr) );638}639else if ( funccall /* && 6 < nr */ ) {640call = NewExpr( T_FUNCCALL_XARGS, SIZE_NARG_CALL(nr) );641}642else if ( /* ! funccall && */ nr <=6 ) {643call = NewExpr( T_PROCCALL_0ARGS+nr, SIZE_NARG_CALL(nr) );644}645else /* if ( ! funccall && 6 < nr ) */ {646call = NewExpr( T_PROCCALL_XARGS, SIZE_NARG_CALL(nr) );647}648649/* get the options record if any */650if (options)651opts = PopExpr();652653/* enter the argument expressions */654for ( i = nr; 1 <= i; i-- ) {655arg = PopExpr();656ARGI_CALL(call,i) = arg;657}658659/* enter the function expression */660func = PopExpr();661FUNC_CALL(call) = func;662663/* wrap up the call with the options */664if (options)665{666wrapper = NewExpr( funccall ? T_FUNCCALL_OPTS : T_PROCCALL_OPTS,6672*sizeof(Expr));668ADDR_EXPR(wrapper)[0] = opts;669ADDR_EXPR(wrapper)[1] = call;670call = wrapper;671}672673/* push the function call */674if ( funccall ) {675PushExpr( call );676}677else {678PushStat( call );679}680}681682683/****************************************************************************684**685*F CodeFuncExprBegin( <narg>, <nloc>, <nams> ) . . code function expr, begin686*F CodeFuncExprEnd( <nr>, <mapsto> ) . . . . code function expression, end687**688** 'CodeFuncExprBegin' is an action to code a function expression. It is689** called when the reader encounters the beginning of a function expression.690** <narg> is the number of arguments (-1 if the function takes a variable691** number of arguments), <nloc> is the number of locals, <nams> is a list of692** local variable names.693**694** 'CodeFuncExprEnd' is an action to code a function expression. It is695** called when the reader encounters the end of a function expression. <nr>696** is the number of statements in the body of the function.697*/698void CodeFuncExprBegin (699Int narg,700Int nloc,701Obj nams,702Int startLine)703{704Obj fexp; /* function expression bag */705Obj fexs; /* function expressions list */706Bag body; /* function body */707Bag old; /* old frame */708Stat stat1; /* first statement in body */709710/* remember the current offset */711PushOffsBody();712713/* and the loop nesting depth */714PushLoopNesting();715716/* create a function expression */717fexp = NewBag( T_FUNCTION, SIZE_FUNC );718NARG_FUNC( fexp ) = narg;719NLOC_FUNC( fexp ) = nloc;720NAMS_FUNC( fexp ) = nams;721CHANGED_BAG( fexp );722723/* give it a functions expressions list */724fexs = NEW_PLIST( T_PLIST, 0 );725SET_LEN_PLIST( fexs, 0 );726FEXS_FUNC( fexp ) = fexs;727CHANGED_BAG( fexp );728729/* give it a body */730body = NewBag( T_BODY, 1024*sizeof(Stat) );731BODY_FUNC( fexp ) = body;732CHANGED_BAG( fexp );733734/* record where we are reading from */735setup_gapname(TLS(Input));736FILENAME_BODY(body) = TLS(Input)->gapname;737STARTLINE_BODY(body) = INTOBJ_INT(startLine);738/* Pr("Coding begin at %s:%d ",(Int)(TLS(Input)->name),TLS(Input)->number);739Pr(" Body id %d\n",(Int)(body),0L); */740TLS(OffsBody) = 0;741TLS(LoopNesting) = 0;742743/* give it an environment */744ENVI_FUNC( fexp ) = TLS(CurrLVars);745CHANGED_BAG( fexp );746747/* switch to this function */748SWITCH_TO_NEW_LVARS( fexp, (narg >0 ? narg : -narg), nloc, old );749(void) old; /* please picky compilers. */750751/* allocate the top level statement sequence */752stat1 = NewStat( T_SEQ_STAT, 8*sizeof(Stat) );753assert( stat1 == FIRST_STAT_CURR_FUNC );754}755756void CodeFuncExprEnd (757UInt nr,758UInt mapsto )759{760Expr expr; /* function expression, result */761Stat stat1; /* single statement of body */762Obj fexp; /* function expression bag */763Obj fexs; /* funct. expr. list of outer func */764UInt len; /* length of func. expr. list */765UInt i; /* loop variable */766767/* get the function expression */768fexp = CURR_FUNC;769assert(!LoopNesting);770771/* get the body of the function */772/* push an addition return-void-statement if neccessary */773/* the function interpreters depend on each function ``returning'' */774if ( nr == 0 ) {775CodeReturnVoid();776nr++;777}778else {779stat1 = PopStat();780PushStat( stat1 );781if ( TNUM_STAT(stat1) != T_RETURN_VOID782&& TNUM_STAT(stat1) != T_RETURN_OBJ )783{784CodeReturnVoid();785nr++;786}787}788789/* if the body is a long sequence, pack the other statements */790if ( 7 < nr ) {791stat1 = PopSeqStat( nr-6 );792PushStat( stat1 );793nr = 7;794}795796/* stuff the first statements into the first statement sequence */797/* Making sure to preserve the line number and file name */798ADDR_STAT(FIRST_STAT_CURR_FUNC)[-1]799= ((Stat)FILENAMEID_STAT(FIRST_STAT_CURR_FUNC) << 48) +800((Stat)LINE_STAT(FIRST_STAT_CURR_FUNC) << 32) +801((nr*sizeof(Stat)) << 8) + T_SEQ_STAT+nr-1;802for ( i = 1; i <= nr; i++ ) {803stat1 = PopStat();804ADDR_STAT(FIRST_STAT_CURR_FUNC)[nr-i] = stat1;805}806807/* make the body smaller */808ResizeBag( BODY_FUNC(fexp), TLS(OffsBody)+NUMBER_HEADER_ITEMS_BODY*sizeof(Obj) );809ENDLINE_BODY(BODY_FUNC(fexp)) = INTOBJ_INT(TLS(Input)->number);810/* Pr(" finished coding %d at line %d\n",(Int)(BODY_FUNC(fexp)), TLS(Input)->number); */811812/* switch back to the previous function */813SWITCH_TO_OLD_LVARS( ENVI_FUNC(fexp) );814815/* restore loop nesting info */816PopLoopNesting();817818/* restore the remembered offset */819PopOffsBody();820821/* if this was inside another function definition, make the expression */822/* and store it in the function expression list of the outer function */823if ( TLS(CurrLVars) != TLS(CodeLVars) ) {824fexs = FEXS_FUNC( CURR_FUNC );825len = LEN_PLIST( fexs );826GROW_PLIST( fexs, len+1 );827SET_LEN_PLIST( fexs, len+1 );828SET_ELM_PLIST( fexs, len+1, fexp );829CHANGED_BAG( fexs );830expr = NewExpr( T_FUNC_EXPR, sizeof(Expr) );831ADDR_EXPR(expr)[0] = (Expr)(len+1);832PushExpr( expr );833}834835/* otherwise, make the function and store it in 'TLS(CodeResult)' */836else {837TLS(CodeResult) = MakeFunction( fexp );838}839840}841842843/****************************************************************************844**845*F CodeIfBegin() . . . . . . . . . . . code if-statement, begin of statement846*F CodeIfElif() . . . . . . . . . . code if-statement, begin of elif-branch847*F CodeIfElse() . . . . . . . . . . code if-statement, begin of else-branch848*F CodeIfBeginBody() . . . . . . . . . . . code if-statement, begin of body849*F CodeIfEndBody( <nr> ) . . . . . . . . . . code if-statement, end of body850*F CodeIfEnd( <nr> ) . . . . . . . . . . code if-statement, end of statement851**852** 'CodeIfBegin' is an action to code an if-statement. It is called when853** the reader encounters the 'if', i.e., *before* the condition is read.854**855** 'CodeIfElif' is an action to code an if-statement. It is called when the856** reader encounters an 'elif', i.e., *before* the condition is read.857**858** 'CodeIfElse' is an action to code an if-statement. It is called when the859** reader encounters an 'else'.860**861** 'CodeIfBeginBody' is an action to code an if-statement. It is called862** when the reader encounters the beginning of the statement body of an863** 'if', 'elif', or 'else' branch, i.e., *after* the condition is read.864**865** 'CodeIfEndBody' is an action to code an if-statement. It is called when866** the reader encounters the end of the statements body of an 'if', 'elif',867** or 'else' branch. <nr> is the number of statements in the body.868**869** 'CodeIfEnd' is an action to code an if-statement. It is called when the870** reader encounters the end of the statement. <nr> is the number of 'if',871** 'elif', or 'else' branches.872*/873void CodeIfBegin ( void )874{875}876877void CodeIfElif ( void )878{879}880881void CodeIfElse ( void )882{883CodeTrueExpr();884}885886void CodeIfBeginBody ( void )887{888}889890void CodeIfEndBody (891UInt nr )892{893/* collect the statements in a statement sequence if necessary */894PushStat( PopSeqStat( nr ) );895}896897void CodeIfEnd (898UInt nr )899{900Stat stat; /* if-statement, result */901Expr cond; /* condition of a branch */902Stat body; /* body of a branch */903UInt hase; /* has else branch */904UInt i; /* loop variable */905906/* peek at the last condition */907body = PopStat();908cond = PopExpr();909hase = (TNUM_EXPR(cond) == T_TRUE_EXPR);910PushExpr( cond );911PushStat( body );912913/* allocate the if-statement */914if ( nr == 1 ) {915stat = NewStat( T_IF, nr * (sizeof(Expr)+sizeof(Stat)) );916}917else if ( nr == 2 && hase ) {918stat = NewStat( T_IF_ELSE, nr * (sizeof(Expr)+sizeof(Stat)) );919}920else if ( ! hase ) {921stat = NewStat( T_IF_ELIF, nr * (sizeof(Expr)+sizeof(Stat)) );922}923else {924stat = NewStat( T_IF_ELIF_ELSE, nr * (sizeof(Expr)+sizeof(Stat)) );925}926927/* enter the branches */928for ( i = nr; 1 <= i; i-- ) {929body = PopStat();930cond = PopExpr();931ADDR_STAT(stat)[2*(i-1)] = cond;932ADDR_STAT(stat)[2*(i-1)+1] = body;933}934935/* push the if-statement */936PushStat( stat );937}938939940/****************************************************************************941**942*F CodeForBegin() . . . . . . . . . code for-statement, begin of statement943*F CodeForIn() . . . . . . . . . . . . . . . . code for-statement, 'in' read944*F CodeForBeginBody() . . . . . . . . . . code for-statement, begin of body945*F CodeForEndBody( <nr> ) . . . . . . . . . code for-statement, end of body946*F CodeForEnd() . . . . . . . . . . . code for-statement, end of statement947**948** 'CodeForBegin' is an action to code a for-statement. It is called when949** the reader encounters the 'for', i.e., *before* the variable is read.950**951** 'CodeForIn' is an action to code a for-statement. It is called when the952** reader encounters the 'in', i.e., *after* the variable is read, but953** *before* the list expression is read.954**955** 'CodeForBeginBody' is an action to code a for-statement. It is called956** when the reader encounters the beginning of the statement body, i.e.,957** *after* the list expression is read.958**959** 'CodeForEndBody' is an action to code a for-statement. It is called when960** the reader encounters the end of the statement body. <nr> is the number961** of statements in the body.962**963** 'CodeForEnd' is an action to code a for-statement. It is called when the964** reader encounters the end of the statement, i.e., immediately after965** 'CodeForEndBody'.966*/967void CodeForBegin ( void )968{969}970971void CodeForIn ( void )972{973Expr var = PopExpr();974if (TNUM_EXPR(var) == T_REF_GVAR)975{976PushGlobalForLoopVariable((UInt)ADDR_EXPR(var)[0]);977}978PushExpr(var);979}980981void CodeForBeginBody ( void )982{983TLS(LoopNesting)++;984}985986void CodeForEndBody (987UInt nr )988{989Stat stat; /* for-statement, result */990UInt type; /* type of for-statement */991Expr var; /* variable */992Expr list; /* list */993Stat stat1; /* single statement of body */994UInt i; /* loop variable */995996/* fix up the case of no statements */997if ( 0 == nr ) {998PushStat( NewStat( T_EMPTY, 0) );999nr = 1;1000}10011002/* collect the statements into a statement sequence if necessary */1003if ( 3 < nr ) {1004PushStat( PopSeqStat( nr ) );1005nr = 1;1006}10071008/* get the list expression */1009list = PopExpr();10101011/* get the variable reference */1012var = PopExpr();10131014if (TNUM_EXPR(var) == T_REF_GVAR)1015PopGlobalForLoopVariable();10161017/* select the type of the for-statement */1018if ( TNUM_EXPR(list) == T_RANGE_EXPR && SIZE_EXPR(list) == 2*sizeof(Expr)1019&& TNUM_EXPR(var) == T_REFLVAR ) {1020type = T_FOR_RANGE + (nr-1);1021}1022else {1023type = T_FOR + (nr-1);1024}10251026/* allocate the for-statement */1027stat = NewStat( type, 2*sizeof(Expr) + nr * sizeof(Stat) );10281029/* enter the body statements */1030for ( i = nr; 1 <= i; i-- ) {1031stat1 = PopStat();1032ADDR_STAT(stat)[i+1] = stat1;1033}10341035/* enter the list expression */1036ADDR_STAT(stat)[1] = list;10371038/* enter the variable reference */1039ADDR_STAT(stat)[0] = var;10401041/* push the for-statement */1042PushStat( stat );10431044/* decrement loop nesting count */1045TLS(LoopNesting)--;1046}10471048void CodeForEnd ( void )1049{1050}105110521053/****************************************************************************1054**1055*F CodeAtomicBegin() . . . . . . . code atomic-statement, begin of statement1056*F CodeAtomicBeginBody() . . . . . . . . code atomic-statement, begin of body1057*F CodeAtomicEndBody( <nr> ) . . . . . . . code atomic-statement, end of body1058*F CodeAtomicEnd() . . . . . . . . . code atomic-statement, end of statement1059**1060** 'CodeAtomicBegin' is an action to code a atomic-statement. It is called1061** when the reader encounters the 'atomic', i.e., *before* the condition is1062** read.1063**1064** 'CodeAtomicBeginBody' is an action to code a atomic-statement. It is1065** called when the reader encounters the beginning of the statement body,1066** i.e., *after* the condition is read.1067**1068** 'CodeAtomicEndBody' is an action to code a atomic-statement. It is called1069** when the reader encounters the end of the statement body. <nr> is the1070** number of statements in the body.1071**1072** 'CodeAtomicEnd' is an action to code a atomic-statement. It is called when1073** the reader encounters the end of the statement, i.e., immediate after1074** 'CodeAtomicEndBody'.1075**1076** These functions are just placeholders for the future HPC-GAP code.1077*/10781079void CodeAtomicBegin ( void )1080{1081}10821083void CodeAtomicBeginBody ( UInt nrexprs )1084{1085PushExpr(INTEXPR_INT(nrexprs));1086return;1087}10881089void CodeAtomicEndBody (1090UInt nrstats )1091{1092Stat stat; /* atomic-statement, result */1093Stat stat1; /* single statement of body */1094UInt i; /* loop variable */1095UInt nrexprs;1096Expr e,qual;109710981099/* fix up the case of no statements */1100if ( 0 == nrstats ) {1101PushStat( NewStat( T_EMPTY, 0) );1102nrstats = 1;1103}11041105/* collect the statements into a statement sequence */1106if ( 1 < nrstats ) {1107stat1 = PopSeqStat( nrstats );1108} else {1109stat1 = PopStat();1110}1111nrexprs = INT_INTEXPR(PopExpr());11121113/* allocate the atomic-statement */1114stat = NewStat( T_ATOMIC, sizeof(Stat) + nrexprs*2*sizeof(Stat) );111511161117/* enter the statement sequence */1118ADDR_STAT(stat)[0] = stat1;111911201121/* enter the expressions */1122for ( i = 2*nrexprs; 1 <= i; i -= 2 ) {1123e = PopExpr();1124qual = PopExpr();1125ADDR_STAT(stat)[i] = e;1126ADDR_STAT(stat)[i-1] = qual;1127}112811291130/* push the atomic-statement */1131PushStat( stat );1132}11331134void CodeAtomicEnd ( void )1135{1136}11371138/****************************************************************************1139**1140*F CodeQualifiedExprBegin() . . . code readonly/readwrite expression start1141*F CodeQualifiedExprEnd() . . . . . code readonly/readwrite expression end1142**1143** These functions code the beginning and end of the readonly/readwrite1144** qualified expressions of an atomic statement.1145*/11461147void CodeQualifiedExprBegin(UInt qual)1148{1149PushExpr(INTEXPR_INT(qual));1150}11511152void CodeQualifiedExprEnd()1153{1154}11551156115711581159/****************************************************************************1160**1161*F CodeWhileBegin() . . . . . . . code while-statement, begin of statement1162*F CodeWhileBeginBody() . . . . . . . . code while-statement, begin of body1163*F CodeWhileEndBody( <nr> ) . . . . . . . code while-statement, end of body1164*F CodeWhileEnd() . . . . . . . . . code while-statement, end of statement1165**1166** 'CodeWhileBegin' is an action to code a while-statement. It is called1167** when the reader encounters the 'while', i.e., *before* the condition is1168** read.1169**1170** 'CodeWhileBeginBody' is an action to code a while-statement. It is1171** called when the reader encounters the beginning of the statement body,1172** i.e., *after* the condition is read.1173**1174** 'CodeWhileEndBody' is an action to code a while-statement. It is called1175** when the reader encounters the end of the statement body. <nr> is the1176** number of statements in the body.1177**1178** 'CodeWhileEnd' is an action to code a while-statement. It is called when1179** the reader encounters the end of the statement, i.e., immediate after1180** 'CodeWhileEndBody'.1181*/1182void CodeWhileBegin ( void )1183{1184}11851186void CodeWhileBeginBody ( void )1187{1188TLS(LoopNesting)++;1189}11901191void CodeWhileEndBody (1192UInt nr )1193{1194Stat stat; /* while-statement, result */1195Expr cond; /* condition */1196Stat stat1; /* single statement of body */1197UInt i; /* loop variable */119811991200/* fix up the case of no statements */1201if ( 0 == nr ) {1202PushStat( NewStat( T_EMPTY, 0) );1203nr = 1;1204}12051206/* collect the statements into a statement sequence if necessary */1207if ( 3 < nr ) {1208PushStat( PopSeqStat( nr ) );1209nr = 1;1210}12111212/* allocate the while-statement */1213stat = NewStat( T_WHILE + (nr-1), sizeof(Expr) + nr * sizeof(Stat) );12141215/* enter the statements */1216for ( i = nr; 1 <= i; i-- ) {1217stat1 = PopStat();1218ADDR_STAT(stat)[i] = stat1;1219}12201221/* enter the condition */1222cond = PopExpr();1223ADDR_STAT(stat)[0] = cond;12241225/* decrmement loop nesting */1226TLS(LoopNesting)--;12271228/* push the while-statement */1229PushStat( stat );1230}12311232void CodeWhileEnd ( void )1233{1234}123512361237/****************************************************************************1238**1239*F CodeRepeatBegin() . . . . . . . code repeat-statement, begin of statement1240*F CodeRepeatBeginBody() . . . . . . . code repeat-statement, begin of body1241*F CodeRepeatEndBody( <nr> ) . . . . . . code repeat-statement, end of body1242*F CodeRepeatEnd() . . . . . . . . . code repeat-statement, end of statement1243**1244** 'CodeRepeatBegin' is an action to code a repeat-statement. It is called1245** when the reader encounters the 'repeat'.1246**1247** 'CodeRepeatBeginBody' is an action to code a repeat-statement. It is1248** called when the reader encounters the beginning of the statement body,1249** i.e., immediately after 'CodeRepeatBegin'.1250**1251** 'CodeRepeatEndBody' is an action to code a repeat-statement. It is1252** called when the reader encounters the end of the statement body, i.e.,1253** *before* the condition is read. <nr> is the number of statements in the1254** body.1255**1256** 'CodeRepeatEnd' is an action to code a repeat-statement. It is called1257** when the reader encounters the end of the statement, i.e., *after* the1258** condition is read.1259*/1260void CodeRepeatBegin ( void )1261{1262}12631264void CodeRepeatBeginBody ( void )1265{1266TLS(LoopNesting)++;1267}12681269void CodeRepeatEndBody (1270UInt nr )1271{1272/* leave the number of statements in the body on the expression stack */1273PushExpr( INTEXPR_INT(nr) );1274TLS(LoopNesting)--;1275}12761277void CodeRepeatEnd ( void )1278{1279Stat stat; /* repeat-statement, result */1280UInt nr; /* number of statements in body */1281Expr cond; /* condition */1282Stat stat1; /* single statement of body */1283Expr tmp; /* temporary */1284UInt i; /* loop variable */12851286/* get the condition */1287cond = PopExpr();12881289/* get the number of statements in the body */1290/* 'CodeUntil' left this number on the expression stack (hack) */1291tmp = PopExpr();1292nr = INT_INTEXPR( tmp );12931294/* fix up the case of no statements */1295if ( 0 == nr ) {1296PushStat( NewStat( T_EMPTY, 0) );1297nr = 1;1298}1299/* collect the statements into a statement sequence if necessary */1300if ( 3 < nr ) {1301PushStat( PopSeqStat( nr ) );1302nr = 1;1303}13041305/* allocate the repeat-statement */1306stat = NewStat( T_REPEAT + (nr-1), sizeof(Expr) + nr * sizeof(Stat) );13071308/* enter the condition */1309ADDR_STAT(stat)[0] = cond;13101311/* enter the statements */1312for ( i = nr; 1 <= i; i-- ) {1313stat1 = PopStat();1314ADDR_STAT(stat)[i] = stat1;1315}13161317/* push the repeat-statement */1318PushStat( stat );1319}132013211322/****************************************************************************1323**1324*F CodeBreak() . . . . . . . . . . . . . . . . . . . . code break-statement1325**1326** 'CodeBreak' is the action to code a break-statement. It is called when1327** the reader encounters a 'break;'.1328*/1329void CodeBreak ( void )1330{1331Stat stat; /* break-statement, result */13321333if (!TLS(LoopNesting))1334SyntaxError("break statement not enclosed in a loop");13351336/* allocate the break-statement */1337stat = NewStat( T_BREAK, 0 * sizeof(Expr) );13381339/* push the break-statement */1340PushStat( stat );1341}13421343/****************************************************************************1344**1345*F CodeContinue() . . . . . . . . . . . . . . . . . . . . code continue-statement1346**1347** 'CodeContinue' is the action to code a continue-statement. It is called when1348** the reader encounters a 'continue;'.1349*/1350void CodeContinue ( void )1351{1352Stat stat; /* continue-statement, result */13531354if (!TLS(LoopNesting))1355SyntaxError("continue statement not enclosed in a loop");13561357/* allocate the continue-statement */1358stat = NewStat( T_CONTINUE, 0 * sizeof(Expr) );13591360/* push the continue-statement */1361PushStat( stat );1362}136313641365/****************************************************************************1366**1367*F CodeReturnObj() . . . . . . . . . . . . . . . code return-value-statement1368**1369** 'CodeReturnObj' is the action to code a return-value-statement. It is1370** called when the reader encounters a 'return <expr>;', but *after* reading1371** the expression <expr>.1372*/1373void CodeReturnObj ( void )1374{1375Stat stat; /* return-statement, result */1376Expr expr; /* expression */13771378/* allocate the return-statement */1379stat = NewStat( T_RETURN_OBJ, sizeof(Expr) );13801381/* enter the expression */1382expr = PopExpr();1383ADDR_STAT(stat)[0] = expr;13841385/* push the return-statement */1386PushStat( stat );1387}138813891390/****************************************************************************1391**1392*F CodeReturnVoid() . . . . . . . . . . . . . . code return-void-statement1393**1394** 'CodeReturnVoid' is the action to code a return-void-statement. It is1395** called when the reader encounters a 'return;'.1396*/1397void CodeReturnVoid ( void )1398{1399Stat stat; /* return-statement, result */14001401/* allocate the return-statement */1402stat = NewStat( T_RETURN_VOID, 0 * sizeof(Expr) );14031404/* push the return-statement */1405PushStat( stat );1406}140714081409/****************************************************************************1410**1411*F CodeOr() . . . . . . . . . . . . . . . . . . . . . . code or-expression1412*F CodeAnd() . . . . . . . . . . . . . . . . . . . . . . code and-expression1413*F CodeNot() . . . . . . . . . . . . . . . . . . . . . . code not-expression1414*F CodeEq() . . . . . . . . . . . . . . . . . . . . . . . code =-expression1415*F CodeNe() . . . . . . . . . . . . . . . . . . . . . . code <>-expression1416*F CodeLt() . . . . . . . . . . . . . . . . . . . . . . . code <-expression1417*F CodeGe() . . . . . . . . . . . . . . . . . . . . . . code >=-expression1418*F CodeGt() . . . . . . . . . . . . . . . . . . . . . . . code >-expression1419*F CodeLe() . . . . . . . . . . . . . . . . . . . . . . code <=-expression1420*F CodeIn() . . . . . . . . . . . . . . . . . . . . . . code in-expression1421*F CodeSum() . . . . . . . . . . . . . . . . . . . . . . . code +-expression1422*F CodeAInv() . . . . . . . . . . . . . . . . . . . code unary --expression1423*F CodeDiff() . . . . . . . . . . . . . . . . . . . . . . code --expression1424*F CodeProd() . . . . . . . . . . . . . . . . . . . . . . code *-expression1425*F CodeInv() . . . . . . . . . . . . . . . . . . . . . . code ^-1-expression1426*F CodeQuo() . . . . . . . . . . . . . . . . . . . . . . . code /-expression1427*F CodeMod() . . . . . . . . . . . . . . . . . . . . . . code mod-expression1428*F CodePow() . . . . . . . . . . . . . . . . . . . . . . . code ^-expression1429**1430** 'CodeOr', 'CodeAnd', 'CodeNot', 'CodeEq', 'CodeNe', 'CodeGt', 'CodeGe',1431** 'CodeIn', 'CodeSum', 'CodeDiff', 'CodeProd', 'CodeQuo', 'CodeMod', and1432** 'CodePow' are the actions to code the respective operator expressions.1433** They are called by the reader *after* *both* operands are read.1434*/1435void CodeOrL ( void )1436{1437}14381439void CodeOr ( void )1440{1441PushBinaryOp( T_OR );1442}14431444void CodeAndL ( void )1445{1446}14471448void CodeAnd ( void )1449{1450PushBinaryOp( T_AND );1451}14521453void CodeNot ( void )1454{1455PushUnaryOp( T_NOT );1456}14571458void CodeEq ( void )1459{1460PushBinaryOp( T_EQ );1461}14621463void CodeNe ( void )1464{1465PushBinaryOp( T_NE );1466}14671468void CodeLt ( void )1469{1470PushBinaryOp( T_LT );1471}14721473void CodeGe ( void )1474{1475PushBinaryOp( T_GE );1476}14771478void CodeGt ( void )1479{1480PushBinaryOp( T_GT );1481}14821483void CodeLe ( void )1484{1485PushBinaryOp( T_LE );1486}14871488void CodeIn ( void )1489{1490PushBinaryOp( T_IN );1491}14921493void CodeSum ( void )1494{1495PushBinaryOp( T_SUM );1496}14971498void CodeAInv ( void )1499{1500Expr expr;1501Int i;15021503expr = PopExpr();1504if ( IS_INTEXPR(expr) && INT_INTEXPR(expr) != -(1L<<NR_SMALL_INT_BITS) ) {1505i = INT_INTEXPR(expr);1506PushExpr( INTEXPR_INT( -i ) );1507}1508else {1509PushExpr( expr );1510PushUnaryOp( T_AINV );1511}1512}15131514void CodeDiff ( void )1515{1516PushBinaryOp( T_DIFF );1517}15181519void CodeProd ( void )1520{1521PushBinaryOp( T_PROD );1522}15231524void CodeInv ( void )1525{1526PushUnaryOp( T_INV );1527}15281529void CodeQuo ( void )1530{1531PushBinaryOp( T_QUO );1532}15331534void CodeMod ( void )1535{1536PushBinaryOp( T_MOD );1537}15381539void CodePow ( void )1540{1541PushBinaryOp( T_POW );1542}154315441545/****************************************************************************1546**1547*F CodeIntExpr( <str> ) . . . . . . . . . . code literal integer expression1548**1549** 'CodeIntExpr' is the action to code a literal integer expression. <str>1550** is the integer as a (null terminated) C character string.1551*/1552void CodeIntExpr (1553Char * str )1554{1555Expr expr; /* expression, result */1556Obj val; /* value = <upp> * <pow> + <low> */1557Obj upp; /* upper part */1558Int pow; /* power */1559Int low; /* lower part */1560Int sign; /* is the integer negative */1561UInt i; /* loop variable */15621563/* get the signs, if any */1564sign = 1;1565i = 0;1566while ( str[i] == '-' ) {1567sign = - sign;1568i++;1569}15701571/* collect the digits in groups of 8 */1572low = 0;1573pow = 1;1574upp = INTOBJ_INT(0);1575while ( str[i] != '\0' ) {1576low = 10 * low + str[i] - '0';1577pow = 10 * pow;1578if ( pow == 100000000L ) {1579upp = SumInt( ProdInt( upp, INTOBJ_INT(pow) ),1580INTOBJ_INT(sign*low) );1581pow = 1;1582low = 0;1583}1584i++;1585}15861587/* compose the integer value (set <val> first to silence 'lint') */1588val = 0;1589if ( upp == INTOBJ_INT(0) ) {1590val = INTOBJ_INT(sign*low);1591}1592else if ( pow == 1 ) {1593val = upp;1594}1595else {1596val = SumInt( ProdInt( upp, INTOBJ_INT(pow) ),1597INTOBJ_INT(sign*low) );1598}15991600/* if it is small enough code it immediately */1601if ( IS_INTOBJ(val) ) {1602expr = INTEXPR_INT( INT_INTOBJ(val) );1603}16041605/* otherwise stuff the value into the values list */1606else {1607expr = NewExpr( T_INT_EXPR, sizeof(UInt) + SIZE_OBJ(val) );1608((UInt *)ADDR_EXPR(expr))[0] = (UInt)TNUM_OBJ(val);1609memcpy((void *)((UInt *)ADDR_EXPR(expr)+1), (void *)ADDR_OBJ(val), (size_t)SIZE_OBJ(val));1610}16111612/* push the expression */1613PushExpr( expr );1614}16151616/****************************************************************************1617**1618*F CodeLongIntExpr( <str> ) . . . code literal long integer expression1619**1620** 'CodeIntExpr' is the action to code a long literal integer1621** expression whose digits are stored in a string GAP object.1622*/1623void CodeLongIntExpr (1624Obj string )1625{1626Expr expr; /* expression, result */1627Obj val; /* value = <upp> * <pow> + <low> */1628Obj upp; /* upper part */1629Int pow; /* power */1630Int low; /* lower part */1631Int sign; /* is the integer negative */1632UInt i; /* loop variable */1633UChar * str;16341635/* get the signs, if any */1636str = CHARS_STRING(string);1637sign = 1;1638i = 0;1639while ( str[i] == '-' ) {1640sign = - sign;1641i++;1642}16431644/* collect the digits in groups of 8 */1645low = 0;1646pow = 1;1647upp = INTOBJ_INT(0);1648while ( str[i] != '\0' ) {1649low = 10 * low + str[i] - '0';1650pow = 10 * pow;1651if ( pow == 100000000L ) {1652upp = SumInt( ProdInt( upp, INTOBJ_INT(pow) ),1653INTOBJ_INT(sign*low) );1654str = CHARS_STRING(string);1655pow = 1;1656low = 0;1657}1658i++;1659}16601661/* compose the integer value (set <val> first to silence 'lint') */1662val = 0;1663if ( upp == INTOBJ_INT(0) ) {1664val = INTOBJ_INT(sign*low);1665}1666else if ( pow == 1 ) {1667val = upp;1668}1669else {1670val = SumInt( ProdInt( upp, INTOBJ_INT(pow) ),1671INTOBJ_INT(sign*low) );1672}16731674/* if it is small enough code it immediately */1675if ( IS_INTOBJ(val) ) {1676expr = INTEXPR_INT( INT_INTOBJ(val) );1677}16781679/* otherwise stuff the value into the values list */1680/* Need to fix this up for GMP integers */1681else {1682expr = NewExpr( T_INT_EXPR, sizeof(UInt) + SIZE_OBJ(val) );1683((UInt *)ADDR_EXPR(expr))[0] = (UInt)TNUM_OBJ(val);1684memcpy((void *)((UInt *)ADDR_EXPR(expr)+1), (void *)ADDR_OBJ(val), (size_t)SIZE_OBJ(val));1685}16861687/* push the expression */1688PushExpr( expr );1689}16901691/****************************************************************************1692**1693*F CodeTrueExpr() . . . . . . . . . . . . . . code literal true expression1694**1695** 'CodeTrueExpr' is the action to code a literal true expression.1696*/1697void CodeTrueExpr ( void )1698{1699PushExpr( NewExpr( T_TRUE_EXPR, 0L ) );1700}170117021703/****************************************************************************1704**1705*F CodeFalseExpr() . . . . . . . . . . . . . . code literal false expression1706**1707** 'CodeFalseExpr' is the action to code a literal false expression.1708*/1709void CodeFalseExpr ( void )1710{1711PushExpr( NewExpr( T_FALSE_EXPR, 0L ) );1712}171317141715/****************************************************************************1716**1717*F CodeCharExpr( <chr> ) . . . . . . . . code a literal character expression1718**1719** 'CodeCharExpr' is the action to code a literal character expression.1720** <chr> is the C character.1721*/1722void CodeCharExpr (1723Char chr )1724{1725Expr litr; /* literal expression, result */17261727/* allocate the character expression */1728litr = NewExpr( T_CHAR_EXPR, sizeof(UChar) );1729((UChar*)ADDR_EXPR(litr))[0] = chr;17301731/* push the literal expression */1732PushExpr( litr );1733}173417351736/****************************************************************************1737**1738*F CodePermCycle( <nrx>, <nrc> ) . . . . code literal permutation expression1739*F CodePerm( <nrc> ) . . . . . . . . . . code literal permutation expression1740**1741** 'CodePermCycle' is an action to code a literal permutation expression.1742** It is called when one cycles is read completely. <nrc> is the number of1743** elements in that cycle. <nrx> is the number of that cycles (i.e., 1 for1744** the first cycle, 2 for the second, and so on).1745**1746** 'CodePerm' is an action to code a literal permutation expression. It is1747** called when the permutation is read completely. <nrc> is the number of1748** cycles.1749*/1750void CodePermCycle (1751UInt nrx,1752UInt nrc )1753{1754Expr cycle; /* cycle, result */1755Expr entry; /* entry of cycle */1756UInt j; /* loop variable */17571758/* allocate the new cycle */1759cycle = NewExpr( T_PERM_CYCLE, nrx * sizeof(Expr) );17601761/* enter the entries */1762for ( j = nrx; 1 <= j; j-- ) {1763entry = PopExpr();1764ADDR_EXPR(cycle)[j-1] = entry;1765}17661767/* push the cycle */1768PushExpr( cycle );1769}17701771void CodePerm (1772UInt nrc )1773{1774Expr perm; /* permutation, result */1775Expr cycle; /* cycle of permutation */1776UInt i; /* loop variable */17771778/* allocate the new permutation */1779perm = NewExpr( T_PERM_EXPR, nrc * sizeof(Expr) );17801781/* enter the cycles */1782for ( i = nrc; 1 <= i; i-- ) {1783cycle = PopExpr();1784ADDR_EXPR(perm)[i-1] = cycle;1785}17861787/* push the permutation */1788PushExpr( perm );17891790}179117921793/****************************************************************************1794**1795*F CodeListExprBegin( <top> ) . . . . . . . . . code list expression, begin1796*F CodeListExprBeginElm( <pos> ) . . . . code list expression, begin element1797*F CodeListExprEndElm() . . . . . . . .. code list expression, end element1798*F CodeListExprEnd( <nr>, <range>, <top>, <tilde> ) . . code list expr, end1799*/1800void CodeListExprBegin (1801UInt top )1802{1803}18041805void CodeListExprBeginElm (1806UInt pos )1807{1808/* push the literal integer value */1809PushExpr( INTEXPR_INT(pos) );1810}18111812void CodeListExprEndElm ( void )1813{1814}18151816void CodeListExprEnd (1817UInt nr,1818UInt range,1819UInt top,1820UInt tilde )1821{1822Expr list; /* list, result */1823Expr entry; /* entry */1824Expr pos; /* position of an entry */1825UInt i; /* loop variable */18261827/* peek at the last position (which is the largest) */1828if ( nr != 0 ) {1829entry = PopExpr();1830pos = PopExpr();1831PushExpr( pos );1832PushExpr( entry );1833}1834else {1835pos = INTEXPR_INT(0);1836}18371838/* allocate the list expression */1839if ( ! range && ! (top && tilde) ) {1840list = NewExpr( T_LIST_EXPR, INT_INTEXPR(pos) * sizeof(Expr) );1841}1842else if ( ! range && (top && tilde) ) {1843list = NewExpr( T_LIST_TILD_EXPR, INT_INTEXPR(pos) * sizeof(Expr) );1844}1845else /* if ( range && ! (top && tilde) ) */ {1846list = NewExpr( T_RANGE_EXPR, INT_INTEXPR(pos) * sizeof(Expr) );1847}18481849/* enter the entries */1850for ( i = nr; 1 <= i; i-- ) {1851entry = PopExpr();1852pos = PopExpr();1853ADDR_EXPR(list)[ INT_INTEXPR(pos)-1 ] = entry;1854}18551856/* push the list */1857PushExpr( list );1858}185918601861/****************************************************************************1862**1863*F CodeStringExpr( <str> ) . . . . . . . . code literal string expression1864*/1865void CodeStringExpr (1866Obj str )1867{1868Expr string; /* string, result */18691870/* allocate the string expression */1871string = NewExpr( T_STRING_EXPR, SIZEBAG_STRINGLEN(GET_LEN_STRING(str)) );18721873/* copy the string */1874memcpy( (void *)ADDR_EXPR(string), ADDR_OBJ(str),1875SIZEBAG_STRINGLEN(GET_LEN_STRING(str)) );18761877/* push the string */1878PushExpr( string );1879}18801881/****************************************************************************1882**1883*F CodeFloatExpr( <str> ) . . . . . . . . code literal float expression1884*/1885#define FLOAT_0_INDEX 11886#define FLOAT_1_INDEX 21887#define MAX_FLOAT_INDEX ((1L<<NR_SMALL_INT_BITS)-2)18881889static UInt GVAR_SAVED_FLOAT_INDEX;1890static UInt NextFloatExprNumber = 3;18911892static UInt NextEagerFloatLiteralNumber = 1;18931894static Obj EAGER_FLOAT_LITERAL_CACHE = 0;1895static Obj CONVERT_FLOAT_LITERAL_EAGER;189618971898static UInt getNextFloatExprNumber( void ) {1899UInt next;1900HashLock(&NextFloatExprNumber);1901if (NextFloatExprNumber > MAX_FLOAT_INDEX)1902next = 0;1903else {1904next = NextFloatExprNumber++;1905}1906HashUnlock(&NextFloatExprNumber);1907return next;1908}19091910static UInt CheckForCommonFloat(Char *str) {1911/* skip leading zeros */1912while (*str == '0')1913str++;1914if (*str == '.')1915/* might be zero literal */1916{1917/* skip point */1918str++;1919/* skip more zeroes */1920while (*str == '0')1921str++;1922/* if we've got to end of string we've got zero. */1923if (!IsDigit(*str))1924return FLOAT_0_INDEX;1925}1926if (*str++ !='1')1927return 0;1928/* might be one literal */1929if (*str++ != '.')1930return 0;1931/* skip zeros */1932while (*str == '0')1933str++;1934if (*str == '\0')1935return FLOAT_1_INDEX;1936if (IsDigit(*str))1937return 0;1938/* must now be an exponent character */1939assert(IsAlpha(*str));1940/* skip it */1941str++;1942/*skip + and - in exponent */1943if (*str == '+' || *str == '-')1944str++;1945/* skip leading zeros in the exponent */1946while (*str == '0')1947str++;1948/* if there's anything but leading zeros this isn't1949a one literal */1950if (*str == '\0')1951return FLOAT_1_INDEX;1952else1953return 0;1954}19551956static void CodeLazyFloatExpr( Char *str, UInt len) {1957UInt ix;19581959/* Lazy case, store the string for conversion at run time */1960Expr fl = NewExpr( T_FLOAT_EXPR_LAZY, 2*sizeof(UInt) +len+1 );1961/* copy the string */1962memcpy( (void *)((char *)ADDR_EXPR(fl)+2*sizeof(UInt)), (void *)str,1963len+1 );19641965*(UInt *)ADDR_EXPR(fl) = len;1966ix = CheckForCommonFloat(str);1967if (!ix)1968ix = getNextFloatExprNumber();1969((UInt *)ADDR_EXPR(fl))[1] = ix;19701971/* push the expression */1972PushExpr( fl );1973}19741975static void CodeEagerFloatExpr( Obj str, Char mark ) {1976/* Eager case, do the conversion now */1977UInt l = GET_LEN_STRING(str);1978Expr fl = NewExpr( T_FLOAT_EXPR_EAGER, sizeof(UInt)* 3 + l + 1);1979Obj v = CALL_2ARGS(CONVERT_FLOAT_LITERAL_EAGER, str, ObjsChar[(Int)mark]);1980assert(EAGER_FLOAT_LITERAL_CACHE);1981assert(IS_PLIST(EAGER_FLOAT_LITERAL_CACHE));1982GROW_PLIST(EAGER_FLOAT_LITERAL_CACHE, NextEagerFloatLiteralNumber);1983SET_ELM_PLIST(EAGER_FLOAT_LITERAL_CACHE, NextEagerFloatLiteralNumber, v);1984CHANGED_BAG(EAGER_FLOAT_LITERAL_CACHE);1985SET_LEN_PLIST(EAGER_FLOAT_LITERAL_CACHE, NextEagerFloatLiteralNumber);1986ADDR_EXPR(fl)[0] = NextEagerFloatLiteralNumber;1987ADDR_EXPR(fl)[1] = l;1988ADDR_EXPR(fl)[2] = (UInt)mark;1989memcpy((void*)(ADDR_EXPR(fl)+3), (void *)CHARS_STRING(str), l+1);1990NextEagerFloatLiteralNumber++;1991PushExpr(fl);1992}19931994void CodeFloatExpr (1995Char * str )1996{19971998UInt l = strlen(str);1999UInt l1 = l;2000Char mark = '\0'; /* initialize to please compilers */2001if (str[l-1] == '_' )2002{2003l1 = l-1;2004mark = '\0';2005}2006else if (str[l-2] == '_')2007{2008l1 = l-2;2009mark = str[l-1];2010}2011if (l1 < l)2012{2013Obj s;2014C_NEW_STRING(s, l1, str);2015CodeEagerFloatExpr(s,mark);2016} else {2017CodeLazyFloatExpr(str, l);2018}2019}20202021/****************************************************************************2022**2023*F CodeLongFloatExpr( <str> ) . . . . . . .code long literal float expression2024*/20252026void CodeLongFloatExpr (2027Obj str )2028{2029Char mark = '\0'; /* initialize to please compilers */20302031/* allocate the float expression */2032UInt l = GET_LEN_STRING(str);2033UInt l1 = l;2034if (CHARS_STRING(str)[l-1] == '_') {2035l1 = l-1;2036mark = '\0';2037} else if (CHARS_STRING(str)[l-2] == '_') {2038l1 = l-2;2039mark = CHARS_STRING(str)[l-1];2040}2041if (l1 < l) {2042CHARS_STRING(str)[l1] = '\0';2043SET_LEN_STRING(str,l1);2044CodeEagerFloatExpr(str, mark);2045} else {2046CodeLazyFloatExpr((Char *)CHARS_STRING(str), l);2047}20482049}205020512052/****************************************************************************2053**2054*F CodeRecExprBegin( <top> ) . . . . . . . . . . . . code record expr, begin2055*F CodeRecExprBeginElmName( <rnam> ) . . . . code record expr, begin element2056*F CodeRecExprBeginElmExpr() . . . . . . . . code record expr, begin element2057*F CodeRecExprEndElmExpr() . . . . . . . . . . code record expr, end element2058*F CodeRecExprEnd( <nr>, <top>, <tilde> ) . . . . . . code record expr, end2059*/2060void CodeRecExprBegin (2061UInt top )2062{2063}20642065void CodeRecExprBeginElmName (2066UInt rnam )2067{2068/* push the record name as integer expressions */2069PushExpr( INTEXPR_INT( rnam ) );2070}20712072void CodeRecExprBeginElmExpr ( void )2073{2074Expr expr;20752076/* convert an integer expression to a record name */2077expr = PopExpr();2078if ( IS_INTEXPR(expr) ) {2079PushExpr( INTEXPR_INT( RNamIntg( INT_INTEXPR(expr) ) ) );2080}2081else {2082PushExpr( expr );2083}2084}20852086void CodeRecExprEndElm ( void )2087{2088}20892090void CodeRecExprEnd (2091UInt nr,2092UInt top,2093UInt tilde )2094{2095Expr record; /* record, result */2096Expr entry; /* entry */2097Expr rnam; /* position of an entry */2098UInt i; /* loop variable */20992100/* allocate the record expression */2101if ( ! (top && tilde) ) {2102record = NewExpr( T_REC_EXPR, nr * 2 * sizeof(Expr) );2103}2104else /* if ( (top && tilde) ) */ {2105record = NewExpr( T_REC_TILD_EXPR, nr * 2 * sizeof(Expr) );2106}21072108/* enter the entries */2109for ( i = nr; 1 <= i; i-- ) {2110entry = PopExpr();2111rnam = PopExpr();2112ADDR_EXPR(record)[2*(i-1)] = rnam;2113ADDR_EXPR(record)[2*(i-1)+1] = entry;2114}21152116/* push the record */2117PushExpr( record );2118}211921202121/****************************************************************************2122**2123*F CodeAssLVar( <lvar> ) . . . . . . . . . . . . . code assignment to local2124**2125** 'CodeAssLVar' is the action to code an assignment to the local variable2126** <lvar> (given by its index). It is called by the reader *after* the2127** right hand side expression is read.2128**2129** An assignment to a local variable is represented by a bag with two2130** subexpressions. The *first* is the local variable, the *second* is the2131** right hand side expression.2132*/2133void CodeAssLVar (2134UInt lvar )2135{2136Stat ass; /* assignment, result */2137Expr rhsx; /* right hand side expression */21382139/* allocate the assignment */2140if ( lvar <= 16 ) {2141ass = NewStat( T_ASS_LVAR + lvar, 2 * sizeof(Stat) );2142}2143else {2144ass = NewStat( T_ASS_LVAR, 2 * sizeof(Stat) );2145}21462147/* enter the right hand side expression */2148rhsx = PopExpr();2149ADDR_STAT(ass)[1] = (Stat)rhsx;21502151/* enter the local variable */2152ADDR_STAT(ass)[0] = (Stat)lvar;21532154/* push the assignment */2155PushStat( ass );2156}215721582159/****************************************************************************2160**2161*F CodeUnbLVar( <lvar> ) . . . . . . . . . . . code unbind a local variable2162*/2163void CodeUnbLVar (2164UInt lvar )2165{2166Stat ass; /* unbind, result */21672168/* allocate the unbind */2169ass = NewStat( T_UNB_LVAR, sizeof(Stat) );21702171/* enter the local variable */2172ADDR_STAT(ass)[0] = (Stat)lvar;21732174/* push the unbind */2175PushStat( ass );2176}217721782179/****************************************************************************2180**2181*F CodeRefLVar( <lvar> ) . . . . . . . . . . . . . . code reference to local2182**2183** 'CodeRefLVar' is the action to code a reference to the local variable2184** <lvar> (given by its index). It is called by the reader when it2185** encounters a local variable.2186**2187** A reference to a local variable is represented immediately (see2188** 'REFLVAR_LVAR').2189*/2190void CodeRefLVar (2191UInt lvar )2192{2193Expr ref; /* reference, result */21942195/* make the reference */2196ref = REFLVAR_LVAR(lvar);21972198/* push the reference */2199PushExpr( ref );2200}220122022203/****************************************************************************2204**2205*F CodeIsbLVar( <lvar> ) . . . . . . . . . . code bound local variable check2206*/2207void CodeIsbLVar (2208UInt lvar )2209{2210Expr ref; /* isbound, result */22112212/* allocate the isbound */2213ref = NewExpr( T_ISB_LVAR, sizeof(Expr) );22142215/* enter the local variable */2216ADDR_EXPR(ref)[0] = (Expr)lvar;22172218/* push the isbound */2219PushExpr( ref );2220}222122222223/****************************************************************************2224**2225*F CodeAssHVar( <hvar> ) . . . . . . . . . . . . . code assignment to higher2226**2227** 'CodeAssHVar' is the action to code an assignment to the higher variable2228** <hvar> (given by its level and index). It is called by the reader2229** *after* the right hand side expression is read.2230**2231** An assignment to a higher variable is represented by a statement bag with2232** two subexpressions. The *first* is the higher variable, the *second* is2233** the right hand side expression.2234*/2235void CodeAssHVar (2236UInt hvar )2237{2238Stat ass; /* assignment, result */2239Expr rhsx; /* right hand side expression */22402241/* allocate the assignment */2242ass = NewStat( T_ASS_HVAR, 2 * sizeof(Stat) );22432244/* enter the right hand side expression */2245rhsx = PopExpr();2246ADDR_STAT(ass)[1] = (Stat)rhsx;22472248/* enter the higher variable */2249ADDR_STAT(ass)[0] = (Stat)hvar;22502251/* push the assignment */2252PushStat( ass );2253}225422552256/****************************************************************************2257**2258*F CodeUnbHVar( <hvar> ) . . . . . . . . . . . . . . . code unbind of higher2259*/2260void CodeUnbHVar (2261UInt hvar )2262{2263Stat ass; /* unbind, result */22642265/* allocate the unbind */2266ass = NewStat( T_UNB_HVAR, sizeof(Stat) );22672268/* enter the higher variable */2269ADDR_STAT(ass)[0] = (Stat)hvar;22702271/* push the unbind */2272PushStat( ass );2273}227422752276/****************************************************************************2277**2278*F CodeRefHVar( <hvar> ) . . . . . . . . . . . . . code reference to higher2279**2280** 'CodeRefHVar' is the action to code a reference to the higher variable2281** <hvar> (given by its level and index). It is called by the reader when2282** it encounters a higher variable.2283**2284** A reference to a higher variable is represented by an expression bag with2285** one subexpression. This is the higher variable.2286*/2287void CodeRefHVar (2288UInt hvar )2289{2290Expr ref; /* reference, result */22912292/* allocate the reference */2293ref = NewExpr( T_REF_HVAR, sizeof(Expr) );22942295/* enter the higher variable */2296ADDR_EXPR(ref)[0] = (Expr)hvar;22972298/* push the reference */2299PushExpr( ref );2300}230123022303/****************************************************************************2304**2305*F CodeIsbHVar( <hvar> ) . . . . . . . . . . . . . . code bound higher check2306*/2307void CodeIsbHVar (2308UInt hvar )2309{2310Expr ref; /* isbound, result */23112312/* allocate the isbound */2313ref = NewExpr( T_ISB_HVAR, sizeof(Expr) );23142315/* enter the higher variable */2316ADDR_EXPR(ref)[0] = (Expr)hvar;23172318/* push the isbound */2319PushExpr( ref );2320}232123222323/****************************************************************************2324**2325*F CodeAssGVar( <gvar> ) . . . . . . . . . . . . . code assignment to global2326**2327** 'CodeAssGVar' is the action to code an assignment to the global variable2328** <gvar>. It is called by the reader *after* the right hand side2329** expression is read.2330**2331** An assignment to a global variable is represented by a statement bag with2332** two subexpressions. The *first* is the global variable, the *second* is2333** the right hand side expression.2334*/2335void CodeAssGVar (2336UInt gvar )2337{2338Stat ass; /* assignment, result */2339Expr rhsx; /* right hand side expression */23402341/* allocate the assignment */2342ass = NewStat( T_ASS_GVAR, 2 * sizeof(Stat) );23432344/* enter the right hand side expression */2345rhsx = PopExpr();2346ADDR_STAT(ass)[1] = (Stat)rhsx;23472348/* enter the global variable */2349ADDR_STAT(ass)[0] = (Stat)gvar;23502351/* push the assignment */2352PushStat( ass );2353}235423552356/****************************************************************************2357**2358*F CodeUnbGVar( <gvar> ) . . . . . . . . . . . . . . . code unbind of global2359*/2360void CodeUnbGVar (2361UInt gvar )2362{2363Stat ass; /* unbind, result */23642365/* allocate the unbind */2366ass = NewStat( T_UNB_GVAR, sizeof(Stat) );23672368/* enter the global variable */2369ADDR_STAT(ass)[0] = (Stat)gvar;23702371/* push the unbind */2372PushStat( ass );2373}237423752376/****************************************************************************2377**2378*F CodeRefGVar( <gvar> ) . . . . . . . . . . . . . code reference to global2379**2380** 'CodeRefGVar' is the action to code a reference to the global variable2381** <gvar>. It is called by the reader when it encounters a global variable.2382**2383** A reference to a global variable is represented by an expression bag with2384** one subexpression. This is the global variable.2385*/2386void CodeRefGVar (2387UInt gvar )2388{2389Expr ref; /* reference, result */23902391/* allocate the reference */2392ref = NewExpr( T_REF_GVAR, sizeof(Expr) );23932394/* enter the global variable */2395ADDR_EXPR(ref)[0] = (Expr)gvar;23962397/* push the reference */2398PushExpr( ref );2399}240024012402/****************************************************************************2403**2404*F CodeIsbGVar( <gvar> ) . . . . . . . . . . . . . . code bound global check2405*/2406void CodeIsbGVar (2407UInt gvar )2408{2409Expr ref; /* isbound, result */24102411/* allocate the isbound */2412ref = NewExpr( T_ISB_GVAR, sizeof(Expr) );24132414/* enter the global variable */2415ADDR_EXPR(ref)[0] = (Expr)gvar;24162417/* push the isbound */2418PushExpr( ref );2419}242024212422/****************************************************************************2423**2424*F CodeAssList() . . . . . . . . . . . . . . . . . code assignment to a list2425*F CodeAsssList() . . . . . . . . . . . code multiple assignment to a list2426*F CodeAssListLevel( <level> ) . . . . . . code assignment to several lists2427*F CodeAsssListLevel( <level> ) . code multiple assignment to several lists2428*/2429void CodeAssListUniv (2430Stat ass,2431Int narg)2432{2433Expr list; /* list expression */2434Expr pos; /* position expression */2435Expr rhsx; /* right hand side expression */2436Int i;24372438/* enter the right hand side expression */2439rhsx = PopExpr();2440ADDR_STAT(ass)[narg+1] = (Stat)rhsx;24412442/* enter the position expression */2443for (i = narg; i > 0; i--) {2444pos = PopExpr();2445ADDR_STAT(ass)[i] = (Stat)pos;2446}24472448/* enter the list expression */2449list = PopExpr();2450ADDR_STAT(ass)[0] = (Stat)list;24512452/* push the assignment */2453PushStat( ass );2454}24552456void CodeAssList ( Int narg )2457{2458Stat ass; /* assignment, result */24592460/* allocate the assignment */2461switch (narg) {2462case 1:2463ass = NewStat( T_ASS_LIST, 3 * sizeof(Stat) );2464break;24652466case 2:2467ass = NewStat(T_ASS2_LIST, 4* sizeof(Stat));2468break;2469default:2470ass = NewStat(T_ASSX_LIST, (narg + 2)*sizeof(Stat));2471}24722473/* let 'CodeAssListUniv' do the rest */2474CodeAssListUniv( ass, narg );2475}24762477void CodeAsssList ( void )2478{2479Stat ass; /* assignment, result */24802481/* allocate the assignment */2482ass = NewStat( T_ASSS_LIST, 3 * sizeof(Stat) );24832484/* let 'CodeAssListUniv' do the rest */2485CodeAssListUniv( ass, 1 );2486}24872488void CodeAssListLevel ( Int narg,2489UInt level )2490{2491Stat ass; /* assignment, result */24922493/* allocate the assignment and enter the level */2494ass = NewStat( T_ASS_LIST_LEV, (narg +3) * sizeof(Stat) );2495ADDR_STAT(ass)[narg+2] = (Stat)level;24962497/* let 'CodeAssListUniv' do the rest */2498CodeAssListUniv( ass, narg );2499}25002501void CodeAsssListLevel (2502UInt level )2503{2504Stat ass; /* assignment, result */25052506/* allocate the assignment and enter the level */2507ass = NewStat( T_ASSS_LIST_LEV, 4 * sizeof(Stat) );2508ADDR_STAT(ass)[3] = (Stat)level;25092510/* let 'CodeAssListUniv' do the rest */2511CodeAssListUniv( ass, 1 );2512}251325142515/****************************************************************************2516**2517*F CodeUnbList() . . . . . . . . . . . . . . . code unbind of list position2518*/2519void CodeUnbList ( Int narg )2520{2521Expr list; /* list expression */2522Expr pos; /* position expression */2523Stat ass; /* unbind, result */2524Int i;25252526/* allocate the unbind */2527ass = NewStat( T_UNB_LIST, (narg+1) * sizeof(Stat) );25282529/* enter the position expressions */2530for (i = narg; i > 0; i--) {2531pos = PopExpr();2532ADDR_STAT(ass)[i] = (Stat)pos;2533}25342535/* enter the list expression */2536list = PopExpr();2537ADDR_STAT(ass)[0] = (Stat)list;25382539/* push the unbind */2540PushStat( ass );2541}254225432544/****************************************************************************2545**2546*F CodeElmList() . . . . . . . . . . . . . . . . . code selection of a list2547*F CodeElmsList() . . . . . . . . . . . . code multiple selection of a list2548*F CodeElmListLevel( <level> ) . . . . . . . code selection of several lists2549*F CodeElmsListLevel( <level> ) . code multiple selection of several lists2550*/2551void CodeElmListUniv (2552Expr ref,2553Int narg)2554{2555Expr list; /* list expression */2556Expr pos; /* position expression */2557Int i;25582559/* enter the position expression */25602561for (i = narg; i > 0; i--) {2562pos = PopExpr();2563ADDR_EXPR(ref)[i] = pos;2564}25652566/* enter the list expression */2567list = PopExpr();2568ADDR_EXPR(ref)[0] = list;25692570/* push the reference */2571PushExpr( ref );2572}25732574void CodeElmList ( Int narg )2575{2576Expr ref; /* reference, result */25772578/* allocate the reference */2579if (narg == 1)2580ref = NewExpr( T_ELM_LIST, 2 * sizeof(Expr) );2581else if (narg == 2)2582ref = NewExpr( T_ELM2_LIST, 3 * sizeof(Expr) );2583else2584ref = NewExpr( T_ELMX_LIST, (narg + 1) *sizeof(Expr));25852586/* let 'CodeElmListUniv' to the rest */2587CodeElmListUniv( ref, narg );25882589}25902591void CodeElmsList ( void )2592{2593Expr ref; /* reference, result */25942595/* allocate the reference */2596ref = NewExpr( T_ELMS_LIST, 2 * sizeof(Expr) );25972598/* let 'CodeElmListUniv' to the rest */2599CodeElmListUniv( ref, 1 );2600}26012602void CodeElmListLevel ( Int narg,2603UInt level )2604{2605Expr ref; /* reference, result */26062607ref = NewExpr( T_ELM_LIST_LEV, (narg+2)*sizeof(Expr));2608ADDR_EXPR(ref)[narg+1] = (Stat)level;260926102611/* let 'CodeElmListUniv' do the rest */2612CodeElmListUniv( ref, narg );2613}26142615void CodeElmsListLevel (2616UInt level )2617{2618Expr ref; /* reference, result */26192620/* allocate the reference and enter the level */2621ref = NewExpr( T_ELMS_LIST_LEV, 3 * sizeof(Expr) );2622ADDR_EXPR(ref)[2] = (Stat)level;26232624/* let 'CodeElmListUniv' do the rest */2625CodeElmListUniv( ref, 1 );2626}262726282629/****************************************************************************2630**2631*F CodeIsbList() . . . . . . . . . . . . . . code bound list position check2632*/2633void CodeIsbList ( Int narg )2634{2635Expr ref; /* isbound, result */2636Expr list; /* list expression */2637Expr pos; /* position expression */2638Int i;26392640/* allocate the isbound */2641ref = NewExpr( T_ISB_LIST, (narg + 1) * sizeof(Expr) );26422643/* enter the position expression */2644for (i = narg; i > 0; i--) {2645pos = PopExpr();2646ADDR_EXPR(ref)[i] = pos;2647}26482649/* enter the list expression */2650list = PopExpr();2651ADDR_EXPR(ref)[0] = list;26522653/* push the isbound */2654PushExpr( ref );2655}265626572658/****************************************************************************2659**2660*F CodeAssRecName( <rnam> ) . . . . . . . . . . code assignment to a record2661*F CodeAssRecExpr() . . . . . . . . . . . . . . code assignment to a record2662*/2663void CodeAssRecName (2664UInt rnam )2665{2666Stat stat; /* assignment, result */2667Expr rec; /* record expression */2668Expr rhsx; /* right hand side expression */26692670/* allocate the assignment */2671stat = NewStat( T_ASS_REC_NAME, 3 * sizeof(Stat) );26722673/* enter the right hand side expression */2674rhsx = PopExpr();2675ADDR_STAT(stat)[2] = (Stat)rhsx;26762677/* enter the name */2678ADDR_STAT(stat)[1] = (Stat)rnam;26792680/* enter the record expression */2681rec = PopExpr();2682ADDR_STAT(stat)[0] = (Stat)rec;26832684/* push the assignment */2685PushStat( stat );2686}26872688void CodeAssRecExpr ( void )2689{2690Stat stat; /* assignment, result */2691Expr rec; /* record expression */2692Expr rnam; /* name expression */2693Expr rhsx; /* right hand side expression */26942695/* allocate the assignment */2696stat = NewStat( T_ASS_REC_EXPR, 3 * sizeof(Stat) );26972698/* enter the right hand side expression */2699rhsx = PopExpr();2700ADDR_STAT(stat)[2] = (Stat)rhsx;27012702/* enter the name expression */2703rnam = PopExpr();2704ADDR_STAT(stat)[1] = (Stat)rnam;27052706/* enter the record expression */2707rec = PopExpr();2708ADDR_STAT(stat)[0] = (Stat)rec;27092710/* push the assignment */2711PushStat( stat );2712}27132714void CodeUnbRecName (2715UInt rnam )2716{2717Stat stat; /* unbind, result */2718Expr rec; /* record expression */27192720/* allocate the unbind */2721stat = NewStat( T_UNB_REC_NAME, 2 * sizeof(Stat) );27222723/* enter the name */2724ADDR_STAT(stat)[1] = (Stat)rnam;27252726/* enter the record expression */2727rec = PopExpr();2728ADDR_STAT(stat)[0] = (Stat)rec;27292730/* push the unbind */2731PushStat( stat );2732}27332734void CodeUnbRecExpr ( void )2735{2736Stat stat; /* unbind, result */2737Expr rec; /* record expression */2738Expr rnam; /* name expression */27392740/* allocate the unbind */2741stat = NewStat( T_UNB_REC_EXPR, 2 * sizeof(Stat) );27422743/* enter the name expression */2744rnam = PopExpr();2745ADDR_STAT(stat)[1] = (Stat)rnam;27462747/* enter the record expression */2748rec = PopExpr();2749ADDR_STAT(stat)[0] = (Stat)rec;27502751/* push the unbind */2752PushStat( stat );2753}275427552756/****************************************************************************2757**2758*F CodeElmRecName( <rnam> ) . . . . . . . . . . code selection of a record2759*F CodeElmRecExpr() . . . . . . . . . . . . . . code selection of a record2760*/2761void CodeElmRecName (2762UInt rnam )2763{2764Expr expr; /* reference, result */2765Expr rec; /* record expresion */27662767/* allocate the reference */2768expr = NewExpr( T_ELM_REC_NAME, 2 * sizeof(Expr) );27692770/* enter the name */2771ADDR_EXPR(expr)[1] = (Expr)rnam;27722773/* enter the record expression */2774rec = PopExpr();2775ADDR_EXPR(expr)[0] = rec;27762777/* push the reference */2778PushExpr( expr );2779}27802781void CodeElmRecExpr ( void )2782{2783Expr expr; /* reference, result */2784Expr rnam; /* name expression */2785Expr rec; /* record expresion */27862787/* allocate the reference */2788expr = NewExpr( T_ELM_REC_EXPR, 2 * sizeof(Expr) );27892790/* enter the expression */2791rnam = PopExpr();2792ADDR_EXPR(expr)[1] = rnam;27932794/* enter the record expression */2795rec = PopExpr();2796ADDR_EXPR(expr)[0] = rec;27972798/* push the reference */2799PushExpr( expr );2800}280128022803/****************************************************************************2804**2805*F CodeIsbRecName( <rnam> ) . . . . . . . . . . . code bound rec name check2806*/2807void CodeIsbRecName (2808UInt rnam )2809{2810Expr expr; /* isbound, result */2811Expr rec; /* record expresion */28122813/* allocate the isbound */2814expr = NewExpr( T_ISB_REC_NAME, 2 * sizeof(Expr) );28152816/* enter the name */2817ADDR_EXPR(expr)[1] = (Expr)rnam;28182819/* enter the record expression */2820rec = PopExpr();2821ADDR_EXPR(expr)[0] = rec;28222823/* push the isbound */2824PushExpr( expr );2825}282628272828/****************************************************************************2829**2830*F CodeIsbRecExpr() . . . . . . . . . . . . . . . code bound rec expr check2831*/2832void CodeIsbRecExpr ( void )2833{2834Expr expr; /* reference, result */2835Expr rnam; /* name expression */2836Expr rec; /* record expresion */28372838/* allocate the isbound */2839expr = NewExpr( T_ISB_REC_EXPR, 2 * sizeof(Expr) );28402841/* enter the expression */2842rnam = PopExpr();2843ADDR_EXPR(expr)[1] = rnam;28442845/* enter the record expression */2846rec = PopExpr();2847ADDR_EXPR(expr)[0] = rec;28482849/* push the isbound */2850PushExpr( expr );2851}285228532854/****************************************************************************2855**2856*F CodeAssPosObj() . . . . . . . . . . . . . . . . code assignment to a list2857*F CodeAsssPosObj() . . . . . . . . . . code multiple assignment to a list2858*F CodeAssPosObjLevel( <level> ) . . . . . code assignment to several lists2859*F CodeAsssPosObjLevel( <level> ) code multiple assignment to several lists2860*/2861void CodeAssPosObjUniv (2862Stat ass )2863{2864Expr list; /* list expression */2865Expr pos; /* position expression */2866Expr rhsx; /* right hand side expression */28672868/* enter the right hand side expression */2869rhsx = PopExpr();2870ADDR_STAT(ass)[2] = (Stat)rhsx;28712872/* enter the position expression */2873pos = PopExpr();2874ADDR_STAT(ass)[1] = (Stat)pos;28752876/* enter the list expression */2877list = PopExpr();2878ADDR_STAT(ass)[0] = (Stat)list;28792880/* push the assignment */2881PushStat( ass );2882}28832884void CodeAssPosObj ( void )2885{2886Stat ass; /* assignment, result */28872888/* allocate the assignment */2889ass = NewStat( T_ASS_POSOBJ, 3 * sizeof(Stat) );28902891/* let 'CodeAssPosObjUniv' do the rest */2892CodeAssPosObjUniv( ass );2893}28942895void CodeAsssPosObj ( void )2896{2897Stat ass; /* assignment, result */28982899/* allocate the assignment */2900ass = NewStat( T_ASSS_POSOBJ, 3 * sizeof(Stat) );29012902/* let 'CodeAssPosObjUniv' do the rest */2903CodeAssPosObjUniv( ass );2904}29052906void CodeAssPosObjLevel (2907UInt level )2908{2909Stat ass; /* assignment, result */29102911/* allocate the assignment and enter the level */2912ass = NewStat( T_ASS_POSOBJ_LEV, 4 * sizeof(Stat) );2913ADDR_STAT(ass)[3] = (Stat)level;29142915/* let 'CodeAssPosObjUniv' do the rest */2916CodeAssPosObjUniv( ass );2917}29182919void CodeAsssPosObjLevel (2920UInt level )2921{2922Stat ass; /* assignment, result */29232924/* allocate the assignment and enter the level */2925ass = NewStat( T_ASSS_POSOBJ_LEV, 4 * sizeof(Stat) );2926ADDR_STAT(ass)[3] = (Stat)level;29272928/* let 'CodeAssPosObjUniv' do the rest */2929CodeAssPosObjUniv( ass );2930}293129322933/****************************************************************************2934**2935*F CodeUnbPosObj() . . . . . . . . . . . . . . . . . code unbind pos object2936*/2937void CodeUnbPosObj ( void )2938{2939Expr list; /* list expression */2940Expr pos; /* position expression */2941Stat ass; /* unbind, result */29422943/* allocate the unbind */2944ass = NewStat( T_UNB_POSOBJ, 2 * sizeof(Stat) );29452946/* enter the position expression */2947pos = PopExpr();2948ADDR_STAT(ass)[1] = (Stat)pos;29492950/* enter the list expression */2951list = PopExpr();2952ADDR_STAT(ass)[0] = (Stat)list;29532954/* push the unbind */2955PushStat( ass );2956}295729582959/****************************************************************************2960**2961*F CodeElmPosObj() . . . . . . . . . . . . . . . . code selection of a list2962*F CodeElmsPosObj() . . . . . . . . . . . code multiple selection of a list2963*F CodeElmPosObjLevel( <level> ) . . . . . . code selection of several lists2964*F CodeElmsPosObjLevel( <level> ) code multiple selection of several lists2965*/2966void CodeElmPosObjUniv (2967Expr ref )2968{2969Expr list; /* list expression */2970Expr pos; /* position expression */29712972/* enter the position expression */2973pos = PopExpr();2974ADDR_EXPR(ref)[1] = pos;29752976/* enter the list expression */2977list = PopExpr();2978ADDR_EXPR(ref)[0] = list;29792980/* push the reference */2981PushExpr( ref );2982}29832984void CodeElmPosObj ( void )2985{2986Expr ref; /* reference, result */29872988/* allocate the reference */2989ref = NewExpr( T_ELM_POSOBJ, 2 * sizeof(Expr) );29902991/* let 'CodeElmPosObjUniv' to the rest */2992CodeElmPosObjUniv( ref );2993}29942995void CodeElmsPosObj ( void )2996{2997Expr ref; /* reference, result */29982999/* allocate the reference */3000ref = NewExpr( T_ELMS_POSOBJ, 2 * sizeof(Expr) );30013002/* let 'CodeElmPosObjUniv' to the rest */3003CodeElmPosObjUniv( ref );3004}30053006void CodeElmPosObjLevel (3007UInt level )3008{3009Expr ref; /* reference, result */30103011/* allocate the reference and enter the level */3012ref = NewExpr( T_ELM_POSOBJ_LEV, 3 * sizeof(Expr) );3013ADDR_EXPR(ref)[2] = (Stat)level;30143015/* let 'CodeElmPosObjUniv' do the rest */3016CodeElmPosObjUniv( ref );3017}30183019void CodeElmsPosObjLevel (3020UInt level )3021{3022Expr ref; /* reference, result */30233024/* allocate the reference and enter the level */3025ref = NewExpr( T_ELMS_POSOBJ_LEV, 3 * sizeof(Expr) );3026ADDR_EXPR(ref)[2] = (Stat)level;30273028/* let 'CodeElmPosObjUniv' do the rest */3029CodeElmPosObjUniv( ref );3030}303130323033/****************************************************************************3034**3035*F CodeIsbPosObj() . . . . . . . . . . . . . . . code bound pos object check3036*/3037void CodeIsbPosObj ( void )3038{3039Expr ref; /* isbound, result */3040Expr list; /* list expression */3041Expr pos; /* position expression */30423043/* allocate the isbound */3044ref = NewExpr( T_ISB_POSOBJ, 2 * sizeof(Expr) );30453046/* enter the position expression */3047pos = PopExpr();3048ADDR_EXPR(ref)[1] = pos;30493050/* enter the list expression */3051list = PopExpr();3052ADDR_EXPR(ref)[0] = list;30533054/* push the isbound */3055PushExpr( ref );3056}305730583059/****************************************************************************3060**3061*F CodeAssComObjName( <rnam> ) . . . . . . . . . code assignment to a record3062*F CodeAssComObjExpr() . . . . . . . . . . . . . code assignment to a record3063*/3064void CodeAssComObjName (3065UInt rnam )3066{3067Stat stat; /* assignment, result */3068Expr rec; /* record expression */3069Expr rhsx; /* right hand side expression */30703071/* allocate the assignment */3072stat = NewStat( T_ASS_COMOBJ_NAME, 3 * sizeof(Stat) );30733074/* enter the right hand side expression */3075rhsx = PopExpr();3076ADDR_STAT(stat)[2] = (Stat)rhsx;30773078/* enter the name */3079ADDR_STAT(stat)[1] = (Stat)rnam;30803081/* enter the record expression */3082rec = PopExpr();3083ADDR_STAT(stat)[0] = (Stat)rec;30843085/* push the assignment */3086PushStat( stat );3087}30883089void CodeAssComObjExpr ( void )3090{3091Stat stat; /* assignment, result */3092Expr rec; /* record expression */3093Expr rnam; /* name expression */3094Expr rhsx; /* right hand side expression */30953096/* allocate the assignment */3097stat = NewStat( T_ASS_COMOBJ_EXPR, 3 * sizeof(Stat) );30983099/* enter the right hand side expression */3100rhsx = PopExpr();3101ADDR_STAT(stat)[2] = (Stat)rhsx;31023103/* enter the name expression */3104rnam = PopExpr();3105ADDR_STAT(stat)[1] = (Stat)rnam;31063107/* enter the record expression */3108rec = PopExpr();3109ADDR_STAT(stat)[0] = (Stat)rec;31103111/* push the assignment */3112PushStat( stat );3113}31143115void CodeUnbComObjName (3116UInt rnam )3117{3118Stat stat; /* unbind, result */3119Expr rec; /* record expression */31203121/* allocate the unbind */3122stat = NewStat( T_UNB_COMOBJ_NAME, 2 * sizeof(Stat) );31233124/* enter the name */3125ADDR_STAT(stat)[1] = (Stat)rnam;31263127/* enter the record expression */3128rec = PopExpr();3129ADDR_STAT(stat)[0] = (Stat)rec;31303131/* push the unbind */3132PushStat( stat );3133}31343135void CodeUnbComObjExpr ( void )3136{3137Stat stat; /* unbind, result */3138Expr rec; /* record expression */3139Expr rnam; /* name expression */31403141/* allocate the unbind */3142stat = NewStat( T_UNB_COMOBJ_EXPR, 2 * sizeof(Stat) );31433144/* enter the name expression */3145rnam = PopExpr();3146ADDR_STAT(stat)[1] = (Stat)rnam;31473148/* enter the record expression */3149rec = PopExpr();3150ADDR_STAT(stat)[0] = (Stat)rec;31513152/* push the unbind */3153PushStat( stat );3154}315531563157/****************************************************************************3158**3159*F CodeElmComObjName( <rnam> ) . . . . . . . . . code selection of a record3160*F CodeElmComObjExpr() . . . . . . . . . . . . . code selection of a record3161*/3162void CodeElmComObjName (3163UInt rnam )3164{3165Expr expr; /* reference, result */3166Expr rec; /* record expresion */31673168/* allocate the reference */3169expr = NewExpr( T_ELM_COMOBJ_NAME, 2 * sizeof(Expr) );31703171/* enter the name */3172ADDR_EXPR(expr)[1] = (Expr)rnam;31733174/* enter the record expression */3175rec = PopExpr();3176ADDR_EXPR(expr)[0] = rec;31773178/* push the reference */3179PushExpr( expr );3180}31813182void CodeElmComObjExpr ( void )3183{3184Expr expr; /* reference, result */3185Expr rnam; /* name expression */3186Expr rec; /* record expresion */31873188/* allocate the reference */3189expr = NewExpr( T_ELM_COMOBJ_EXPR, 2 * sizeof(Expr) );31903191/* enter the expression */3192rnam = PopExpr();3193ADDR_EXPR(expr)[1] = rnam;31943195/* enter the record expression */3196rec = PopExpr();3197ADDR_EXPR(expr)[0] = rec;31983199/* push the reference */3200PushExpr( expr );3201}320232033204/****************************************************************************3205**3206*F CodeIsbComObjName( <rname> ) . . . . . code bound com object name check3207*/3208void CodeIsbComObjName (3209UInt rnam )3210{3211Expr expr; /* isbound, result */3212Expr rec; /* record expresion */32133214/* allocate the isbound */3215expr = NewExpr( T_ISB_COMOBJ_NAME, 2 * sizeof(Expr) );32163217/* enter the name */3218ADDR_EXPR(expr)[1] = (Expr)rnam;32193220/* enter the record expression */3221rec = PopExpr();3222ADDR_EXPR(expr)[0] = rec;32233224/* push the isbound */3225PushExpr( expr );3226}32273228/****************************************************************************3229**3230*F CodeIsbComObjExpr() . . . . . . . . . . code bound com object expr check3231*/3232void CodeIsbComObjExpr ( void )3233{3234Expr expr; /* reference, result */3235Expr rnam; /* name expression */3236Expr rec; /* record expresion */32373238/* allocate the isbound */3239expr = NewExpr( T_ISB_COMOBJ_EXPR, 2 * sizeof(Expr) );32403241/* enter the expression */3242rnam = PopExpr();3243ADDR_EXPR(expr)[1] = rnam;32443245/* enter the record expression */3246rec = PopExpr();3247ADDR_EXPR(expr)[0] = rec;32483249/* push the isbound */3250PushExpr( expr );3251}325232533254/****************************************************************************3255**3256*F CodeEmpty() . . . . code an empty statement3257**3258*/32593260extern void CodeEmpty( void )3261{3262Stat stat;3263stat = NewStat(T_EMPTY, 0);3264PushStat( stat );3265}32663267/****************************************************************************3268**3269*F CodeInfoBegin() . . . . . . . . . . . . . start coding of Info statement3270*F CodeInfoMiddle() . . . . . . . . . shift to coding printable arguments3271*F CodeInfoEnd( <narg> ) . . Info statement complete, <narg> things to print3272**3273** These actions deal with the Info statement, which is coded specially,3274** because not all of its arguments are always evaluated.3275**3276** Only CodeInfoEnd actually does anything3277*/3278void CodeInfoBegin ( void )3279{3280}32813282void CodeInfoMiddle ( void )3283{3284}32853286void CodeInfoEnd (3287UInt narg )3288{3289Stat stat; /* we build the statement here */3290Expr expr; /* expression */3291UInt i; /* loop variable */32923293/* allocate the new statement */3294stat = NewStat( T_INFO, SIZE_NARG_INFO(2+narg) );32953296/* narg only counts the printable arguments */3297for ( i = narg + 2; 0 < i; i-- ) {3298expr = PopExpr();3299ARGI_INFO( stat, i ) = expr;3300}33013302/* push the statement */3303PushStat( stat );3304}330533063307/****************************************************************************3308**3309*F CodeAssertBegin() . . . . . . . start interpretation of Assert statement3310*F CodeAsseerAfterLevel() . . called after the first argument has been read3311*F CodeAssertAfterCondition() called after the second argument has been read3312*F CodeAssertEnd2Args() . . . . called after reading the closing parenthesis3313*F CodeAssertEnd3Args() . . . . called after reading the closing parenthesis3314**3315** Only the End functions actually do anything3316*/3317void CodeAssertBegin ( void )3318{3319}33203321void CodeAssertAfterLevel ( void )3322{3323}33243325void CodeAssertAfterCondition ( void )3326{3327}33283329void CodeAssertEnd2Args ( void )3330{3331Stat stat; /* we build the statement here */33323333stat = NewStat( T_ASSERT_2ARGS, 2*sizeof(Expr) );33343335ADDR_STAT(stat)[1] = PopExpr(); /* condition */3336ADDR_STAT(stat)[0] = PopExpr(); /* level */33373338PushStat( stat );3339}33403341void CodeAssertEnd3Args ( void )3342{3343Stat stat; /* we build the statement here */33443345stat = NewStat( T_ASSERT_3ARGS, 3*sizeof(Expr) );33463347ADDR_STAT(stat)[2] = PopExpr(); /* message */3348ADDR_STAT(stat)[1] = PopExpr(); /* condition */3349ADDR_STAT(stat)[0] = PopExpr(); /* level */33503351PushStat( stat );3352}33533354/****************************************************************************3355**3356*F SaveBody( <body> ) . . . . . . . . . . . . . . . workspace saving method3357**3358** A body is made up of statements and expressions, and these are all3359** organised to regular boundaries based on the types Stat and Expr, which3360** are currently both UInt3361**3362** String literals should really be saved byte-wise, to be safe across machines3363** of different endianness, but this would mean parsing the bag as we save it3364** which it would be nice to avoid just now.3365*/3366void SaveBody ( Obj body )3367{3368UInt i;3369UInt *ptr;3370ptr = (UInt *) ADDR_OBJ(body);3371/* Save the new inforation in the body */3372for (i =0; i < NUMBER_HEADER_ITEMS_BODY; i++)3373SaveSubObj((Obj)(*ptr++));3374/* and the rest */3375for (; i < (SIZE_OBJ(body)+sizeof(UInt)-1)/sizeof(UInt); i++)3376SaveUInt(*ptr++);3377}33783379/****************************************************************************3380**3381*F LoadBody( <body> ) . . . . . . . . . . . . . . . workspace loading method3382**3383** A body is made up of statements and expressions, and these are all3384** organised to regular boundaries based on the types Stat and Expr, which3385** are currently both UInt3386**3387*/3388void LoadBody ( Obj body )3389{3390UInt i;3391UInt *ptr;3392ptr = (UInt *) ADDR_OBJ(body);3393for (i =0; i < NUMBER_HEADER_ITEMS_BODY; i++)3394*(Obj *)(ptr++) = LoadSubObj();3395for (; i < (SIZE_OBJ(body)+sizeof(UInt)-1)/sizeof(UInt); i++)3396*ptr++ = LoadUInt();3397}339833993400/****************************************************************************3401**3402*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *3403*/34043405/****************************************************************************3406**3407*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures3408*/3409static Int InitKernel (3410StructInitInfo * module )3411{3412/* install the marking functions for function body bags */3413InfoBags[ T_BODY ].name = "function body bag";3414InitMarkFuncBags( T_BODY, MarkThreeSubBags );34153416SaveObjFuncs[ T_BODY ] = SaveBody;3417LoadObjFuncs[ T_BODY ] = LoadBody;34183419/* Allocate function bodies in the public data space */3420MakeBagTypePublic(T_BODY);34213422/* make the result variable known to Gasman */3423InitGlobalBag( &CodeResult, "CodeResult" );34243425InitGlobalBag( &FilenameCache, "FilenameCache" );34263427/* allocate the statements and expressions stacks */3428InitGlobalBag( &TLS(StackStat), "TLS(StackStat)" );3429InitGlobalBag( &TLS(StackExpr), "TLS(StackExpr)" );34303431/* some functions and globals needed for float conversion */3432InitCopyGVar( "EAGER_FLOAT_LITERAL_CACHE", &EAGER_FLOAT_LITERAL_CACHE);3433InitFopyGVar( "CONVERT_FLOAT_LITERAL_EAGER", &CONVERT_FLOAT_LITERAL_EAGER);34343435/* return success */3436return 0;3437}343834393440/****************************************************************************3441**3442*F InitLibrary( <module> ) . . . . . . . initialise library data structures3443*/3444static Int InitLibrary (3445StructInitInfo * module )3446{3447UInt gv;3448Obj cache;3449/* allocate the statements and expressions stacks */3450TLS(StackStat) = NewBag( T_BODY, 64*sizeof(Stat) );3451TLS(StackExpr) = NewBag( T_BODY, 64*sizeof(Expr) );3452FilenameCache = NEW_PLIST(T_PLIST, 0);34533454GVAR_SAVED_FLOAT_INDEX = GVarName("SavedFloatIndex");34553456gv = GVarName("EAGER_FLOAT_LITERAL_CACHE");3457cache = NEW_PLIST(T_PLIST+IMMUTABLE, 1000L);3458SET_LEN_PLIST(cache,0);3459AssGVar(gv, cache);34603461/* return success */3462return 0;3463}34643465/****************************************************************************3466**3467*F PostRestore( <module> ) . . . . . . . recover3468*/3469static Int PostRestore (3470StructInitInfo * module )3471{3472GVAR_SAVED_FLOAT_INDEX = GVarName("SavedFloatIndex");3473NextFloatExprNumber = INT_INTOBJ(VAL_GVAR(GVAR_SAVED_FLOAT_INDEX));3474return 0;3475}347634773478/****************************************************************************3479**3480*F PreSave( <module> ) . . . . . . . clean up before saving3481*/3482static Int PreSave (3483StructInitInfo * module )3484{3485UInt i;34863487/* Can't save in mid-parsing */3488if (TLS(CountExpr) || TLS(CountStat))3489return 1;34903491/* push the FP cache index out into a GAP Variable */3492AssGVar(GVAR_SAVED_FLOAT_INDEX, INTOBJ_INT(NextFloatExprNumber));34933494/* clean any old data out of the statement and expression stacks */3495for (i = 0; i < SIZE_BAG(TLS(StackStat))/sizeof(UInt); i++)3496ADDR_OBJ(TLS(StackStat))[i] = (Obj)0;3497for (i = 0; i < SIZE_BAG(TLS(StackExpr))/sizeof(UInt); i++)3498ADDR_OBJ(TLS(StackExpr))[i] = (Obj)0;3499/* return success */3500return 0;3501}3502350335043505/****************************************************************************3506**3507*F InitInfoCode() . . . . . . . . . . . . . . . . . table of init functions3508*/3509static StructInitInfo module = {3510MODULE_BUILTIN, /* type */3511"code", /* name */35120, /* revision entry of c file */35130, /* revision entry of h file */35140, /* version */35150, /* crc */3516InitKernel, /* initKernel */3517InitLibrary, /* initLibrary */35180, /* checkInit */3519PreSave, /* preSave */35200, /* postSave */3521PostRestore /* postRestore */3522};35233524StructInitInfo * InitInfoCode ( void )3525{3526return &module;3527}352835293530/****************************************************************************3531**35323533*E code.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here3534*/353535363537