Skip to content

Commit 54f8ff4

Browse files
committed
Introduce EXPR_ELM_MAT_LEV and simplify EXPR_ELMS_LIST_LEV
Since 2e850b0, at most two indices in "[]" are allowed. Handling the two possible cases explicitly allows to simplify some parts of the code and makes one's life easier when manipulating syntax trees. However, this obviously is a breaking change.
1 parent f049274 commit 54f8ff4

File tree

4 files changed

+81
-24
lines changed

4 files changed

+81
-24
lines changed

src/code.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,7 +2428,7 @@ void CodeElmList(CodeState * cs, Int narg)
24282428
// allocate the reference
24292429
if (narg == 1)
24302430
ref = NewExpr(cs, EXPR_ELM_LIST, 2 * sizeof(Expr));
2431-
else // if (narg == 2)
2431+
else // if (narg == 2)
24322432
ref = NewExpr(cs, EXPR_ELM_MAT, 3 * sizeof(Expr));
24332433

24342434
// let 'CodeElmListUniv' to the rest
@@ -2450,8 +2450,13 @@ void CodeElmListLevel(CodeState * cs, Int narg, UInt level)
24502450
{
24512451
Expr ref; // reference, result
24522452

2453+
GAP_ASSERT(narg == 1 || narg == 2);
2454+
24532455
// allocate the reference and enter the level
2454-
ref = NewExpr(cs, EXPR_ELM_LIST_LEV, (narg + 2) * sizeof(Expr));
2456+
if (narg == 1)
2457+
ref = NewExpr(cs, EXPR_ELM_LIST_LEV, 3 * sizeof(Expr));
2458+
else // if (narg == 2)
2459+
ref = NewExpr(cs, EXPR_ELM_MAT_LEV, 4 * sizeof(Expr));
24552460
WRITE_EXPR(cs, ref, narg + 1, level);
24562461

24572462
// let 'CodeElmListUniv' do the rest

src/code.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ enum EXPR_TNUM {
534534
EXPR_ELM_MAT,
535535
EXPR_ELMS_LIST,
536536
EXPR_ELM_LIST_LEV,
537+
EXPR_ELM_MAT_LEV,
537538
EXPR_ELMS_LIST_LEV,
538539
EXPR_ISB_LIST,
539540

src/syntaxtree.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,14 @@ static const CompilerT Compilers[] = {
904904
COMPILER_(
905905
EXPR_ELM_MAT, ARG_EXPR_("list"), ARG_EXPR_("row"), ARG_EXPR_("col")),
906906
COMPILER_(EXPR_ELMS_LIST, ARG_EXPR_("list"), ARG_EXPR_("poss")),
907+
COMPILER_(EXPR_ELM_MAT_LEV,
908+
ARG_EXPR_("matrices"),
909+
ARG_EXPR_("row"),
910+
ARG_EXPR_("col"),
911+
ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
907912
COMPILER_(EXPR_ELM_LIST_LEV,
908913
ARG_EXPR_("lists"),
909-
ARGS_EXPR("pos"),
914+
ARG_EXPR_("pos"),
910915
ARG_EXPR("level", ObjInt_UInt, SyntaxTreeCodeObjInt)),
911916
COMPILER_(EXPR_ELMS_LIST_LEV,
912917
ARG_EXPR_("lists"),

src/vars.c

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -825,33 +825,71 @@ static Obj EvalElmListLevel(Expr expr)
825825
{
826826
Obj lists; // lists, left operand
827827
Obj pos; // position, right operand
828-
Obj ixs;
829828
UInt level; // level
830-
Int narg;
831-
Int i;
829+
Obj ixs;
832830

833831
// evaluate lists (if this works, then <lists> is nested <level> deep,
834832
// checking it is nested <level>+1 deep is done by 'ElmListLevel')
835833
lists = EVAL_EXPR(READ_EXPR(expr, 0));
836-
narg = SIZE_EXPR(expr)/sizeof(Expr) -2;
837-
ixs = NEW_PLIST(T_PLIST, narg);
838-
for (i = 1; i <= narg; i++) {
839-
pos = EVAL_EXPR( READ_EXPR(expr, i));
840-
SET_ELM_PLIST(ixs, i, pos);
841-
CHANGED_BAG(ixs);
842-
}
843-
SET_LEN_PLIST(ixs, narg);
844-
// get the level
845-
level = READ_EXPR(expr, narg + 1);
834+
pos = EVAL_EXPR(READ_EXPR(expr, 1));
835+
level = READ_EXPR(expr, 2);
836+
837+
ixs = NEW_PLIST(T_PLIST, 1);
838+
SET_ELM_PLIST(ixs, 1, pos);
839+
CHANGED_BAG(ixs);
840+
SET_LEN_PLIST(ixs, 1);
846841

847842
// select the elements from several lists (store them in <lists>)
848-
ElmListLevel( lists, ixs, level );
843+
ElmListLevel(lists, ixs, level);
849844

850845
// return the elements
851846
return lists;
852847
}
853848

854849

850+
/****************************************************************************
851+
**
852+
*F EvalElmMatLevel(<expr>) . . . . . . select elements of several matrices
853+
**
854+
** 'EvalElmMatLevel' evaluates the matrix element expression <expr> of the
855+
** form '<list>...{<positions>}...[<row>,<col>]', where there may actually
856+
** be several '{<positions>}' selections between <list> and '[<position>]'.
857+
** The number of those is called the level. 'EvalElmMatLevel' goes that
858+
** deep into the left operand and selects the element at <row>,<col> from
859+
** each of those matrices. For example, if the level is 1, the left operand
860+
** must be a list of matrices and 'EvalElmMatLevel' selects the element at
861+
** <row>,<col> from each of the matrices and returns the list of those
862+
** values.
863+
*/
864+
static Obj EvalElmMatLevel(Expr expr)
865+
{
866+
Obj matrices; // matrices
867+
Obj row; // row position
868+
Obj col; // column position
869+
UInt level; // level
870+
Obj ixs;
871+
872+
// evaluate matrices (if this works, then <matrices> is nested <level>
873+
// deep, checking it is nested <level>+1 deep is done by 'ElmListLevel')
874+
matrices = EVAL_EXPR(READ_EXPR(expr, 0));
875+
row = EVAL_EXPR(READ_EXPR(expr, 1));
876+
col = EVAL_EXPR(READ_EXPR(expr, 2));
877+
level = READ_EXPR(expr, 3);
878+
879+
ixs = NEW_PLIST(T_PLIST, 2);
880+
SET_ELM_PLIST(ixs, 1, row);
881+
SET_ELM_PLIST(ixs, 2, col);
882+
CHANGED_BAG(ixs);
883+
SET_LEN_PLIST(ixs, 2);
884+
885+
// select the elements from several matrices (store them in <matrices>)
886+
ElmListLevel(matrices, ixs, level);
887+
888+
// return the elements
889+
return matrices;
890+
}
891+
892+
855893
/****************************************************************************
856894
**
857895
*F EvalElmsListLevel(<expr>) . . . select several elements of several lists
@@ -1010,7 +1048,7 @@ static void PrintAsssList(Stat stat)
10101048
*F ExprHasNonZeroListLevel(<expr>) . . . . . . . . . . . . . . . . . . . . .
10111049
**
10121050
** Every 'EXPR_ELMS_LIST' or 'EXPR_ELMS_LIST_LEV' increments the list level.
1013-
** 'EXPR_ELM_LIST_LEV' has a non-zero list level.
1051+
** 'EXPR_ELM_LIST_LEV' and 'EXPR_ELM_MAT_LEV' have non-zero list levels.
10141052
** Every other expression should have level 0.
10151053
**
10161054
** If a list access happens at level zero ('EXPR_ELM_LIST', 'EXPR_ELM_MAT'
@@ -1021,6 +1059,7 @@ static BOOL ExprHasNonZeroListLevel(Expr list)
10211059
{
10221060
return TNUM_EXPR(list) == EXPR_ELMS_LIST ||
10231061
TNUM_EXPR(list) == EXPR_ELM_LIST_LEV ||
1062+
TNUM_EXPR(list) == EXPR_ELM_MAT_LEV ||
10241063
TNUM_EXPR(list) == EXPR_ELMS_LIST_LEV;
10251064
}
10261065

@@ -1070,16 +1109,21 @@ static void PrintElmMat(Expr expr)
10701109

10711110
static void PrintElmListLevel(Expr expr)
10721111
{
1073-
Int i;
1074-
Int narg = SIZE_EXPR(expr)/sizeof(Expr) -2 ;
10751112
Pr("%2>", 0, 0);
10761113
PrintExpr(READ_EXPR(expr, 0));
10771114
Pr("%<[", 0, 0);
10781115
PrintExpr(READ_EXPR(expr, 1));
1079-
for (i = 2; i <= narg; i++) {
1080-
Pr("%<, %>", 0, 0);
1081-
PrintExpr(READ_EXPR(expr, i));
1082-
}
1116+
Pr("%<]", 0, 0);
1117+
}
1118+
1119+
static void PrintElmMatLevel(Expr expr)
1120+
{
1121+
Pr("%2>", 0, 0);
1122+
PrintExpr(READ_EXPR(expr, 0));
1123+
Pr("%<[", 0, 0);
1124+
PrintExpr(READ_EXPR(expr, 1));
1125+
Pr("%<, %>", 0, 0);
1126+
PrintExpr(READ_EXPR(expr, 2));
10831127
Pr("%<]", 0, 0);
10841128
}
10851129

@@ -2282,8 +2326,10 @@ static Int InitKernel (
22822326
// install executors, evaluators, and printers for matrix elements
22832327
InstallExecStatFunc(STAT_ASS_MAT, ExecAssMat);
22842328
InstallEvalExprFunc(EXPR_ELM_MAT, EvalElmMat);
2329+
InstallEvalExprFunc(EXPR_ELM_MAT_LEV, EvalElmMatLevel);
22852330
InstallPrintStatFunc(STAT_ASS_MAT, PrintAssMat);
22862331
InstallPrintExprFunc(EXPR_ELM_MAT, PrintElmMat);
2332+
InstallPrintExprFunc(EXPR_ELM_MAT_LEV, PrintElmMatLevel);
22872333

22882334
// install executors, evaluators, and printers for record elements
22892335
InstallExecStatFunc( STAT_ASS_REC_NAME , ExecAssRecName);

0 commit comments

Comments
 (0)