-
Notifications
You must be signed in to change notification settings - Fork 26
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
Branches Proof Of Concept #174
base: main
Are you sure you want to change the base?
Conversation
|
||
uint8_t* instruction; | ||
|
||
ptrdiff_t exit_branches[10]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
@@ -262,6 +282,112 @@ static tag_markup_t internal_block_body_parse(block_body_t *body, parse_context_ | |||
return unknown_tag; | |||
} | |||
|
|||
VALUE parse_single_binary_comparison(VALUE markup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind of scrappy, need a better abstraction for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
Condition
object. When executed it evaluates theCondition
and pushes the RTEST of the result onto the stackProcess
When an if tag is encountered we add an
OP_EVAL_CONDITION
for theif
statement and add anOP_BRANCH_UNLESS
operation that jumps to the next clause (or endif)Parsing then resumes as normal by calling
internal_block_body_parse
, wheninternal_block_body_parse
returns with an unknown tag we check if its one of the clauses we can handle likeelse
if so we add an unconditionalOP_BRANCH
which exits to the next endif and continue parsing the tokens for theelse
block.Nesting is handled through recursion.
Heres an example of a liquid if block and its corresponding bytecode.
Theres a more complete example in
test.rb
with elsif and nesting.Limitations of the POC
I'm sure theres a lot thats missing, heres the stuff im aware of: