Skip to content

Commit

Permalink
Add constant support
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson committed Sep 16, 2017
1 parent b8aea44 commit 5937453
Show file tree
Hide file tree
Showing 12 changed files with 479 additions and 19 deletions.
30 changes: 28 additions & 2 deletions doc/ref/language.xml
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,35 @@ Certain special facilities are provided for manipulating global
variables which are not available for other types of variable (such as
local variables or function arguments).
<P/>
First, such variables may be marked <E>read-only</E>. In which case
First, such variables may be marked <E>read-only</E> using
<Ref Func="MakeReadOnlyGlobal"/>. In which case
attempts to change them will fail. Most of the global variables
defined in the &GAP; library are so marked.
defined in the &GAP; library are so marked. <E>read-only</E> variables
can be made read-write again by calling <Ref Func="MakeReadWriteGlobal"/>.
GAP also features <E>constant</E> variables, which are created by calling
<Ref Func="MakeConstantGlobal"/>. Constant variables can never be changed.
In some cases, GAP can optimise code which uses <E>constant</E> variables,
as their value never changes. This can be observed by printing the
function back out.
<Example><![CDATA[
gap> globali := 1 + 2;;
gap> globalb := true;;
gap> MakeConstantGlobal("globali");
gap> MakeConstantGlobal("globalb");
gap> f := function()
> if globalb then
> return globali + 1;
> else
> return globali + 2;
> fi;
> end;;
gap> Print(f);
function ( )
return 3 + 1;
end
]]></Example>


<P/>
Second, a group of functions are supplied for accessing and altering the
values assigned to global variables. Use of these functions differs
Expand Down
20 changes: 20 additions & 0 deletions lib/global.g
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ UNBIND_GLOBAL := UNB_GVAR;

IS_READ_ONLY_GLOBAL := IsReadOnlyGVar;

#############################################################################
##
#F IS_CONSTANT_GLOBAL ( <name> ) determine if a global variable is constant
##
## IS_CONSTANT_GLOBAL ( <name> ) returns true if the global variable
## named by the string <name> is constant and false otherwise (the default)
##

IS_CONSTANT_GLOBAL := IsConstantGVar;

#############################################################################
##
#F MAKE_READ_ONLY_GLOBAL ( <name> ) . . . . make a global variable read-only
Expand All @@ -90,6 +100,16 @@ MAKE_READ_ONLY_GLOBAL := MakeReadOnlyGVar;

MAKE_READ_WRITE_GLOBAL := MakeReadWriteGVar;

#############################################################################
##
#F MAKE_CONSTANT_GLOBAL ( <name> )
##
## MAKE_CONSTANT_GLOBAL ( <name> ) marks the global variable named
## by the string <name> as constant
##

MAKE_CONSTANT_GLOBAL := MakeConstantGVar;

#############################################################################
##
#V REREADING set to true inside a Reread, changes much
Expand Down
35 changes: 35 additions & 0 deletions lib/global.gd
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ DeclareGlobalFunction("UnbindGlobal");
##
DeclareGlobalFunction("IsReadOnlyGlobal");

#############################################################################
##
#F IsConstantGlobal( <name> ) . determine if a global variable is constant
##
## <ManSection>
## <Func Name="IsConstantGlobal" Arg='name'/>
##
## <Description>
## IsConstantGlobal ( <A>name</A> ) returns true if the global variable
## named by the string <A>name</A> is constant and false otherwise (the default).
## </Description>
## </ManSection>
##
DeclareGlobalFunction("IsConstantGlobal");


#############################################################################
##
Expand Down Expand Up @@ -153,6 +168,26 @@ DeclareGlobalFunction("MakeReadOnlyGlobal");
DeclareGlobalFunction("MakeReadWriteGlobal");


#############################################################################
##
#F MakeConstantGlobal( <name> ) . . . . . make a global variable constant
##
## <ManSection>
## <Func Name="MakeConstantGlobal" Arg='name'/>
##
## <Description>
## MakeConstantGlobal ( <A>name</A> ) marks the global variable named
## by the string <A>name</A> as constant. A constant variable can never
## be changed or made read-write. Constant variables can only take an
## integer value, <C>true</C> or <C>false</C>.
## <P/>
## A warning is given if <A>name</A> is already constant.
## </Description>
## </ManSection>
##
DeclareGlobalFunction("MakeConstantGlobal");


#############################################################################
##
#F BindGlobal( <name>, <val> ) . . . . . . sets a global variable `safely'
Expand Down
49 changes: 44 additions & 5 deletions lib/global.gi
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,31 @@ InstallGlobalFunction( IsReadOnlyGlobal,
return isro;
end);

#############################################################################
##
#F IsConstantGlobal ( <name> ) . determine if a global variable is constant
##
## IsConstantGlobal ( <name> ) returns true if the global variable
## named by the string <name> is constant and false otherwise (the default)
##

InstallGlobalFunction( IsConstantGlobal,
function (name)
local isro;
CheckGlobalName( name );
isro := IS_CONSTANT_GLOBAL(name);
Info( InfoGlobal, 3,
"IsConstantGlobal: called for ", name, " returned ", isro);
return isro;
end);


#############################################################################
##
#F MakeReadOnlyGlobal ( <name> ) . . . . . make a global variable read-only
##
## MakeReadOnlyGlobal ( <name> ) marks the global variable named
## by the string <name> as read-only.
## MakeReadOnlyGlobal ( <name> ) marks the global variable named by the
## string <name> as read-only.
##
## A warning is given if <name> has no value bound to it or if it is
## already read-only
Expand Down Expand Up @@ -182,10 +200,10 @@ end);
##
#F MakeReadWriteGlobal ( <name> ) . . . . make a global variable read-write
##
## MakeReadWriteGlobal ( <name> ) marks the global variable named
## by the string <name> as read-write
## MakeReadWriteGlobal ( <name> ) marks the global variable named by the
## string <name> as read-write
##
## A warning is given if <name> is already read-write
## A warning is given if <name> is already read-write
##

InstallGlobalFunction( MakeReadWriteGlobal,
Expand All @@ -199,6 +217,27 @@ InstallGlobalFunction( MakeReadWriteGlobal,
MAKE_READ_WRITE_GLOBAL( name );
end);

#############################################################################
##
#F MakeConstantGlobal ( <name> ) . . . . . make a global variable constant
##
## MakeConstantGlobal ( <name> ) marks the global variable named by the
## string <name> as constant
##
## A warning is given if <name> is already constant
##

InstallGlobalFunction( MakeConstantGlobal,
function (name)
CheckGlobalName( name );
if IS_CONSTANT_GLOBAL( name ) then
Info( InfoWarning + InfoGlobal, 1,
"MakeConstantGlobal: ", name, " already constant");
fi;
Info( InfoGlobal, 2, "MakeConstantGlobal: called for ", name);
MAKE_CONSTANT_GLOBAL( name );
end);


#############################################################################
##
Expand Down
59 changes: 51 additions & 8 deletions src/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,16 +973,54 @@ void CodeIfEnd (
{
Stat stat; /* if-statement, result */
Expr cond; /* condition of a branch */
Stat body; /* body of a branch */
UInt hase; /* has else branch */
UInt i; /* loop variable */
Expr cond1 = 0; /* first condition */
Expr cond2 = 0; /* second condition */

/* peek at the last two conditions */
cond1 = PopExpr();
hase = (TNUM_EXPR(cond1) == T_TRUE_EXPR);
if (nr == 2) {
cond2 = PopExpr();
PushExpr(cond2);
}
PushExpr(cond1);

// Some optimisation cases
if (nr == 1) {
if (TNUM_EXPR(cond1) == T_TRUE_EXPR) {
// Leave statement
PopExpr();
return;
}
else if (TNUM_EXPR(cond1) == T_FALSE_EXPR) {
// Remove entire if statement
PopStat();
PopExpr();
PushStat(NewStat(T_EMPTY, 0));
return;
}
}

/* peek at the last condition */
body = PopStat();
cond = PopExpr();
hase = (TNUM_EXPR(cond) == T_TRUE_EXPR);
PushExpr( cond );
PushStat( body );
if (nr == 2 && hase) {
if (TNUM_EXPR(cond2) == T_TRUE_EXPR) {
// Leave 'true' case
PopStat();
PopExpr();
PopExpr();
return;
}
else if (TNUM_EXPR(cond2) == T_FALSE_EXPR) {
// Leave 'false' case
Stat body = PopStat();
PopExpr();
PopStat();
PopExpr();
PushStat(body);
return;
}
}

/* allocate the if-statement */
if ( nr == 1 ) {
Expand All @@ -1000,7 +1038,7 @@ void CodeIfEnd (

/* enter the branches */
for ( i = nr; 1 <= i; i-- ) {
body = PopStat();
Stat body = PopStat();
cond = PopExpr();
ADDR_STAT(stat)[2*(i-1)] = cond;
ADDR_STAT(stat)[2*(i-1)+1] = body;
Expand Down Expand Up @@ -1616,6 +1654,11 @@ void CodePow ( void )
}


void CodeGAPSmallInt(Obj val)
{
PushExpr(INTEXPR_INT(INT_INTOBJ(val)));
}

/****************************************************************************
**
*F CodeIntExpr( <str> ) . . . . . . . . . . code literal integer expression
Expand Down
1 change: 1 addition & 0 deletions src/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ extern void CodePow ( void );
** 'CodeIntExpr' is the action to code a literal integer expression. <str>
** is the integer as a (null terminated) C character string.
*/
extern void CodeGAPSmallInt(Obj obj);
extern void CodeIntExpr (
Char * str );
extern void CodeLongIntExpr (
Expand Down
Loading

0 comments on commit 5937453

Please sign in to comment.