Closed THinnerichs closed 3 months ago
I've reworked the interpreter so that it doesn't depend on the order of the rules anymore.
I think this is a general principle we can follow for any interpreter. The main idea is to tag every derivation rule with the symbol of the operation:
function get_relevant_tags(grammar::ContextSensitiveGrammar)
tags = Dict{Int,Symbol}()
for (ind, r) in pairs(grammar.rules)
tags[ind] = if typeof(r) == Symbol
r
else
@match r.head begin
:block => :OpSeq
:call => r.args[1]
end
end
end
return tags
end
The interpreter can then be written by matching the tags:
function interpret(prog::AbstractRuleNode, grammartags::Dict{Int,Symbol}, state::RobotState)
rule_node = get_rule(prog)
@match grammartags[rule_node] begin
:OpSeq => interpret(prog.children[2], grammartags, interpret(prog.children[1], grammar, state)) # (Operation ; Sequence)
:moveRight => !(state.robot_x == state.size) ? RobotState(state.holds_ball, state.robot_x+1, state.robot_y, state.ball_x, state.ball_y, state.size) : state #moveright
:moveDown => !(state.robot_y == state.size) ? RobotState(state.holds_ball, state.robot_x, state.robot_y+1, state.ball_x, state.ball_y, state.size) : state #moveDown
:moveLeft => !(state.robot_x == 1) ? RobotState(state.holds_ball, state.robot_x-1, state.robot_y, state.ball_x, state.ball_y, state.size) : state #moveLeft
:moveUp => !(state.robot_y == 1) ? RobotState(state.holds_ball, state.robot_x, state.robot_y-1, state.ball_x, state.ball_y, state.size) : state #moveUp
:drop => state.holds_ball == 1 ? RobotState(0, state.robot_x, state.robot_y, state.robot_x, state.robot_y, state.size) : state #drop
:grab => can_pickup(state) ? RobotState(1, state.robot_x, state.robot_y, state.ball_x, state.ball_y, state.size) : state # grab
:IF => interpret(prog.children[1], grammartags, state) ? interpret(prog.children[2], grammartags, state) : interpret(prog.children[3], grammartags, state) #If statement
:WHILE => command_while(prog.children[1], prog.children[2], grammartags, state) # while loop
:atTop => state.robot_y == 1 #atTop
:atBottom => state.robot_y == state.size #atBottom
:atLeft => state.robot_x == 1 #atLeft
:atRight => state.robot_x == state.size #atRight
:notAtTop => !(state.robot_y == 1) #notAtTop
:notAtBottom => !(state.robot_y == state.size) # notAtBottom
:notAtLeft => !(state.robot_x == 1) #notAtLeft
:notAtRight => !(state.robot_x == state.size) # notAtRight
_ => interpret(prog.children[1], grammartags, state) # Start operation Transformation ControlStatement
end
end
@sebdumancic If you could review one of the benchmarks, that would be great.
At the moment, StringState
s are not equal when their respective str
s are equal. We could either do
Base.==(a::StringState, b::StringState) = a.str == b.str
or check for one of the pointers being nothing
with
Base.==(a::StringState, b::StringState) = a.str == b.str && (a.pointer === nothing || b.pointer === nothing)
During search we get a lot of solutions like
Solution: problem_b156 61 WHILE(isNotUppercase(), drop())
which is basically an if then
statement, but is shorter as only two holes have to be filled.
I really like the tests! I think this is already a really great standard. I don't think we need more than this.
2 comments:
_arg_1, _arg_2, ...
as names for input symbols.