Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile functions to a GAP record #1132

Closed
wants to merge 58 commits into from

Conversation

markuspf
Copy link
Member

@markuspf markuspf commented Feb 9, 2017

This PR adds a function SYNTAX_TREE which takes as its argument a GAP function and returns a record that describes that function's syntax tree. This will be useful for a range of purposes such as code analysis, constant folding, optimisations, testing, which can be done in GAP instead of awkwardly coding it in C.

The code is somewhat mirroring the Compiler/Executor/Coder (All three already look very similar), but could be simplified quite a bit, because bar some more complex constructs, most statements/expressions are binary or ternary operations and nothing else.

It is still lacking tests and documentation, and probably has quite a few bugs left, but I'll open this PR for people to see what's going on.

It also does not support HPC-GAP syntax at all at this point.

It would probably be quite nice to have an "inverse" of this function that takes a syntax tree and compiles it back to GAP bytecode, as well as exploring the option of hooking into the parser directly to produce the syntax tree instead of interpreting bytecode.

@markuspf markuspf added do not merge PRs which are not yet ready to be merged (e.g. submitted for discussion, or test results) kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements labels Feb 9, 2017
@markuspf markuspf self-assigned this Feb 9, 2017
Copy link
Contributor

@ChrisJefferson ChrisJefferson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some minor early comments

src/syntaxtree.c Outdated
return result;
}

/* TODO: Can we still identify whether a string was triple quoted? */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, internally the strings are stored identically

src/syntaxtree.c Outdated
result = NewSyntaxTreeNode("And",3);

AssPRec(result, RNamName("left"), SyntaxTreeExpr(ADDR_EXPR(expr)[0]));
AssPRec(result, RNamName("right"), SyntaxTreeExpr(ADDR_EXPR(expr)[0]));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[1]?

In general I might be tempted to make this into some kind of macro, just because we have lots of 2-op and 1-op cases to handle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I was planning that anyway (there must be a comment around somewhere that says that these functions are all the same and they should be a macro or inline function)

src/syntaxtree.c Outdated
return result;
}

Obj SyntaxTreePermExpr (Expr expr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be easier / simpler to just give a GAP permutation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, since you can have expressions in the permutation entries, I want to be able to reflect that, i.e. what do you do with

for i in [1..5] do
  p := p * (i, i+5);
od;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, I keep forgetting you can do that :)

@codecov-io
Copy link

codecov-io commented Feb 20, 2017

Codecov Report

Merging #1132 into master will decrease coverage by 33.1%.
The diff coverage is 3.49%.

@@             Coverage Diff             @@
##           master    #1132       +/-   ##
===========================================
- Coverage   60.92%   27.82%   -33.11%     
===========================================
  Files         997       92      -905     
  Lines      301950    55297   -246653     
  Branches    13036    10750     -2286     
===========================================
- Hits       183968    15385   -168583     
+ Misses     115333    38380    -76953     
+ Partials     2649     1532     -1117
Impacted Files Coverage Δ
src/gap.c 44.53% <ø> (-11.74%) ⬇️
src/syntaxtree.c 3.49% <3.49%> (ø)
src/fibhash.h 0% <0%> (-100%) ⬇️
src/objfgelm.h 0% <0%> (-100%) ⬇️
src/pperm.h 0% <0%> (-100%) ⬇️
src/trans.c 3.16% <0%> (-95.73%) ⬇️
src/tietze.c 1.2% <0%> (-82.78%) ⬇️
src/pperm.c 2.22% <0%> (-75.92%) ⬇️
src/objset.c 9.62% <0%> (-72.98%) ⬇️
src/vector.c 19.9% <0%> (-72.26%) ⬇️
... and 987 more

@markuspf markuspf force-pushed the compile-to-gap-record branch from b2dceca to 94d0dd0 Compare February 20, 2017 12:22
src/syntaxtree.c Outdated

Obj SyntaxTreeUnknownBool(Expr expr)
{
/* compile the expression and check that the value is boolean */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Irrelevant nitpick: Could we perhaps agree to not space pad comments in new code? I think it's a horrible waste of time to go through functions to ensure comments are padded consistently; and if one doesn't do it, it looks just weird. Your TODO comments already follow this, after all (and I'd leave the #include comments alone for now; those are changed by a perl script in the hpc-merge branch anyway)

src/syntaxtree.c Outdated
siz = SIZE_EXPR(expr) - sizeof(UInt);
typ = *(UInt *)ADDR_EXPR(expr);
value = C_MAKE_INTEGER_BAG(siz, typ);
for ( i = 0; i < siz/INTEGER_UNIT_SIZE; i++ ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This for and the if a few lines above are inconsistenly formatted, if(FOO) vs. for ( FOO ). Perhaps use clang-format on the new code?

src/syntaxtree.c Outdated
#endif
}
if (siz <= 8) {
value = C_NORMALIZE_64BIT(value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I wasn't even aware of C_NORMALIZE_64BIT and the above code (which comes from the compiler, I think?). I'd prefer if all integer normalization was handled by code in gmpints.c, and if code outside assumed as little as possible about the internal format of the integer code, so that future changes require less code changes outside of gmpints.c. I'll try to understand this code and see if I can suggest an alternative...

src/syntaxtree.c Outdated

result = NewSyntaxTreeNode("IntExpr");;

if(IS_INTEXPR(expr)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never noticed this before, but: T_INT_EXPR vs. T_INTEXPR seems needlessly confusing; perhaps we should rename one or both, to indicate one is immediate / small, the other big?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also gotta love how EvalIntExpr of course deals with T_INT_EXPR but not T_INTEXPR ;-).

src/syntaxtree.c Outdated
#elif INTEGER_UNIT_SIZE == 8
C_SET_LIMB8(value, i, ((UInt8 *)((UInt *)ADDR_EXPR(expr) + 1))[i]);
#else
#error unsupported INTEGER_UNIT_SIZE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I am not sure I understand why you need to use these compiler macros in order to convert the expression into an integer object. Can't you just do what EvalIntExpr does?

src/syntaxtree.c Outdated
return result;
}

Obj SyntaxTreeIntExpr(Expr expr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, and other functions like it, is never referenced anywhere. So I guess it's incomplete work in progress?

*/
StructInitInfo * InitInfoSyntaxTree ( void );

#endif // GAP_COMPILER_H
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be GAP_SYNTAXTREE_H not GAP_COMPILER_H

src/syntaxtree.c Outdated

{ T_REFLVAR, SyntaxTreeDefaultExpr, "T_REFLVAR", 0, { } },

DEF_EXPR_DEFAULT(41),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives a compiler error for me:

../../src/syntaxtree.c:1344:5: error: initializer element is not a compile-time constant
    DEF_EXPR_DEFAULT(41),
    ^~~~~~~~~~~~~~~~~~~~

src/syntaxtree.c Outdated

/* compile the statements */
for ( i = 1; i <= nr; i++ ) {
SET_ELM_PLIST(list, i, SyntaxTreeStat( ADDR_STAT( stat )[i-1] ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

../../src/syntaxtree.c:553:32: warning: implicit declaration of function 'SyntaxTreeStat' is invalid in C99
      [-Wimplicit-function-declaration]
        SET_ELM_PLIST(list, i, SyntaxTreeStat( ADDR_STAT( stat )[i-1] ) );
                               ^

... and lot of other warnings... WIP code?

@markuspf markuspf force-pushed the compile-to-gap-record branch from 1710701 to 8a1dcb4 Compare February 26, 2017 01:31
@markuspf markuspf force-pushed the compile-to-gap-record branch from 706d81e to 9385490 Compare March 8, 2017 22:03
src/syntaxtree.c Outdated
}

static ArgT[] = {
ARG_COMPILER("rnam", SyntaxTreeCompiler);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ARG_COMPILER doesn't seem to be defined anywhere? Maybe ARG_ is meant?

@markuspf markuspf force-pushed the compile-to-gap-record branch from 9385490 to 029a653 Compare May 27, 2017 16:14
static const CompilerT ExprCompilers[];

#define COMPILER_ARITY(...) \
(sizeof((ArgT []){ __VA_ARGS__ }) / sizeof(ArgT))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this macro (or rather, its expansion) trips up HPC-GAP.

No idea how hard it would be to teach ward about this C99 feature. But of course a simple fix would be to forgo variadics, and simply have several COMPILER macros: for 0, 1, 2, ... args. But that's certainly less elegant :-/

@markuspf markuspf force-pushed the compile-to-gap-record branch from 7abb8a8 to 4ad3dba Compare September 26, 2017 14:49
@markuspf markuspf force-pushed the compile-to-gap-record branch from 4ad3dba to fe52f6f Compare October 3, 2017 15:19
@stevelinton
Copy link
Contributor

syntaxtree.gd seems to be missing

gap> Read( Filename(DirectoriesLibrary( "tst/testinstall/syntax" ), "testsyntax.g" ) );
gap> i := PositionsProperty([1..Length(trees)], i -> trees[i] <> expect_trees[i]);;
gap> List(trees{ i }, x -> x.name);
[ ]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails, actually gives [ "stat_test_if", "test_comobj" ]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The former failure is probably because we now optimize if true and if false away in certain cases.

@markuspf markuspf closed this Oct 24, 2017
@markuspf
Copy link
Member Author

I don't see a point in leaving this open if work-in-progress leads to distraction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do not merge PRs which are not yet ready to be merged (e.g. submitted for discussion, or test results) kind: enhancement Label for issues suggesting enhancements; and for pull requests implementing enhancements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants