Conversation
|
|
||
| uint8_t* instruction; | ||
|
|
||
| ptrdiff_t exit_branches[10]; |
There was a problem hiding this comment.
This array is used to keep track of all the branches that need to jump to "endif". This needs to use a dynamically sized list here, something like cbuffer.
There was a problem hiding this comment.
The offsets get stored with the instruction in 16 bits. assuming this is ok for a jump offset, otherwise need to store them somewhere else.
| return unknown_tag; | ||
| } | ||
|
|
||
| VALUE parse_single_binary_comparison(VALUE markup) { |
There was a problem hiding this comment.
Only supports parsing 1 binary comparison, need to extend this to support more conditions.
| *exit_end++ = vm_assembler_open_branch(body_code, OP_BRANCH); | ||
|
|
||
| // Calculate the offset that would jump to here, this is where the <if> jumps to if it fails the condition. | ||
| jump = (ptrdiff_t) (body_code->instructions.data_end - body_code->instructions.data); |
There was a problem hiding this comment.
Calculating indices since cbuffer can realloc.
|
|
||
| // Resolve the open branch from the <if> with the calculated offset. | ||
| vm_assembler_close_branch(body_code, open_branch, jump); | ||
| open_branch = -1; |
There was a problem hiding this comment.
using -1 as a sentinel value to indicate no open branch.
| render_score_increment += 1; | ||
| body->as.intermediate.blank = false; | ||
| break; | ||
| } else if ( |
There was a problem hiding this comment.
This is kind of scrappy, need a better abstraction for this.
There was a problem hiding this comment.
I was thinking of something along the lines of #96 so we could pick the right parsing handler from ruby land.
cdefd97 to
9639195
Compare
9639195 to
ea77f6e
Compare
| render_score_increment += 1; | ||
| body->as.intermediate.blank = false; |
There was a problem hiding this comment.
not sure what these two do, might be updating them incorrectly.
What
This PR implements a proof of concept for handling branches in the Liquid VM.
How
OP Codes
To implement branches i've added 3 OP codes:
Conditionobject. When executed it evaluates theConditionand pushes the RTEST of the result onto the stackProcess
When an if tag is encountered we add an
OP_EVAL_CONDITIONfor theifstatement and add anOP_BRANCH_UNLESSoperation that jumps to the next clause (or endif)Parsing then resumes as normal by calling
internal_block_body_parse, wheninternal_block_body_parsereturns with an unknown tag we check if its one of the clauses we can handle likeelseif so we add an unconditionalOP_BRANCHwhich exits to the next endif and continue parsing the tokens for theelseblock.Nesting is handled through recursion.
Heres an example of a liquid if block and its corresponding bytecode.
Theres a more complete example in
test.rbwith elsif and nesting.Limitations of the POC
I'm sure theres a lot thats missing, heres the stuff im aware of: