Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6c6b437

Browse files
committed
Add BF compiler
1 parent df9f622 commit 6c6b437

File tree

5 files changed

+807
-157
lines changed

5 files changed

+807
-157
lines changed

lib/syntax_tree.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
require_relative "syntax_tree/pattern"
2727
require_relative "syntax_tree/search"
2828

29+
require_relative "syntax_tree/dsl"
2930
require_relative "syntax_tree/yarv"
3031
require_relative "syntax_tree/compiler"
32+
require_relative "syntax_tree/yarv/bf"
33+
require_relative "syntax_tree/yarv/disassembler"
3134

3235
# Syntax Tree is a suite of tools built on top of the internal CRuby parser. It
3336
# provides the ability to generate a syntax tree from source, as well as the

lib/syntax_tree/dsl.rb

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# frozen_string_literal: true
2+
3+
module SyntaxTree
4+
module DSL
5+
def ARef(collection, index)
6+
ARef.new(collection: collection, index: index, location: Location.default)
7+
end
8+
9+
def ARefField(collection, index)
10+
ARefField.new(collection: collection, index: index, location: Location.default)
11+
end
12+
13+
def Args(parts)
14+
Args.new(parts: parts, location: Location.default)
15+
end
16+
17+
def ArgParen(arguments)
18+
ArgParen.new(arguments: arguments, location: Location.default)
19+
end
20+
21+
def Assign(target, value)
22+
Assign.new(target: target, value: value, location: Location.default)
23+
end
24+
25+
def Assoc(key, value)
26+
Assoc.new(key: key, value: value, location: Location.default)
27+
end
28+
29+
def Binary(left, operator, right)
30+
Binary.new(left: left, operator: operator, right: right, location: Location.default)
31+
end
32+
33+
def BlockNode(opening, block_var, bodystmt)
34+
BlockNode.new(opening: opening, block_var: block_var, bodystmt: bodystmt, location: Location.default)
35+
end
36+
37+
def BodyStmt(statements, rescue_clause, else_keyword, else_clause, ensure_clause)
38+
BodyStmt.new(statements: statements, rescue_clause: rescue_clause, else_keyword: else_keyword, else_clause: else_clause, ensure_clause: ensure_clause, location: Location.default)
39+
end
40+
41+
def CallNode(receiver, operator, message, arguments)
42+
CallNode.new(receiver: receiver, operator: operator, message: message, arguments: arguments, location: Location.default)
43+
end
44+
45+
def Case(keyword, value, consequent)
46+
Case.new(keyword: keyword, value: value, consequent: consequent, location: Location.default)
47+
end
48+
49+
def FloatLiteral(value)
50+
FloatLiteral.new(value: value, location: Location.default)
51+
end
52+
53+
def GVar(value)
54+
GVar.new(value: value, location: Location.default)
55+
end
56+
57+
def HashLiteral(lbrace, assocs)
58+
HashLiteral.new(lbrace: lbrace, assocs: assocs, location: Location.default)
59+
end
60+
61+
def Ident(value)
62+
Ident.new(value: value, location: Location.default)
63+
end
64+
65+
def IfNode(predicate, statements, consequent)
66+
IfNode.new(predicate: predicate, statements: statements, consequent: consequent, location: Location.default)
67+
end
68+
69+
def Int(value)
70+
Int.new(value: value, location: Location.default)
71+
end
72+
73+
def Kw(value)
74+
Kw.new(value: value, location: Location.default)
75+
end
76+
77+
def LBrace(value)
78+
LBrace.new(value: value, location: Location.default)
79+
end
80+
81+
def MethodAddBlock(call, block)
82+
MethodAddBlock.new(call: call, block: block, location: Location.default)
83+
end
84+
85+
def Next(arguments)
86+
Next.new(arguments: arguments, location: Location.default)
87+
end
88+
89+
def Op(value)
90+
Op.new(value: value, location: Location.default)
91+
end
92+
93+
def OpAssign(target, operator, value)
94+
OpAssign.new(target: target, operator: operator, value: value, location: Location.default)
95+
end
96+
97+
def Period(value)
98+
Period.new(value: value, location: Location.default)
99+
end
100+
101+
def Program(statements)
102+
Program.new(statements: statements, location: Location.default)
103+
end
104+
105+
def ReturnNode(arguments)
106+
ReturnNode.new(arguments: arguments, location: Location.default)
107+
end
108+
109+
def Statements(body)
110+
Statements.new(nil, body: body, location: Location.default)
111+
end
112+
113+
def SymbolLiteral(value)
114+
SymbolLiteral.new(value: value, location: Location.default)
115+
end
116+
117+
def VarField(value)
118+
VarField.new(value: value, location: Location.default)
119+
end
120+
121+
def VarRef(value)
122+
VarRef.new(value: value, location: Location.default)
123+
end
124+
125+
def When(arguments, statements, consequent)
126+
When.new(arguments: arguments, statements: statements, consequent: consequent, location: Location.default)
127+
end
128+
end
129+
end

lib/syntax_tree/yarv.rb

Lines changed: 0 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -799,163 +799,6 @@ def serialize(insn)
799799
end
800800
end
801801

802-
# This class is responsible for taking a compiled instruction sequence and
803-
# walking through it to generate equivalent Ruby code.
804-
class Disassembler
805-
module DSL
806-
def Args(parts)
807-
Args.new(parts: parts, location: Location.default)
808-
end
809-
810-
def ArgParen(arguments)
811-
ArgParen.new(arguments: arguments, location: Location.default)
812-
end
813-
814-
def Assign(target, value)
815-
Assign.new(target: target, value: value, location: Location.default)
816-
end
817-
818-
def Binary(left, operator, right)
819-
Binary.new(left: left, operator: operator, right: right, location: Location.default)
820-
end
821-
822-
def CallNode(receiver, operator, message, arguments)
823-
CallNode.new(receiver: receiver, operator: operator, message: message, arguments: arguments, location: Location.default)
824-
end
825-
826-
def FloatLiteral(value)
827-
FloatLiteral.new(value: value, location: Location.default)
828-
end
829-
830-
def Ident(value)
831-
Ident.new(value: value, location: Location.default)
832-
end
833-
834-
def Int(value)
835-
Int.new(value: value, location: Location.default)
836-
end
837-
838-
def Period(value)
839-
Period.new(value: value, location: Location.default)
840-
end
841-
842-
def Program(statements)
843-
Program.new(statements: statements, location: Location.default)
844-
end
845-
846-
def ReturnNode(arguments)
847-
ReturnNode.new(arguments: arguments, location: Location.default)
848-
end
849-
850-
def Statements(body)
851-
Statements.new(nil, body: body, location: Location.default)
852-
end
853-
854-
def VarField(value)
855-
VarField.new(value: value, location: Location.default)
856-
end
857-
858-
def VarRef(value)
859-
VarRef.new(value: value, location: Location.default)
860-
end
861-
end
862-
863-
include DSL
864-
attr_reader :iseq
865-
866-
def initialize(iseq)
867-
@iseq = iseq
868-
end
869-
870-
def to_ruby
871-
stack = []
872-
873-
iseq.insns.each do |insn|
874-
# skip line numbers and events
875-
next unless insn.is_a?(Array)
876-
877-
case insn[0]
878-
when :getlocal_WC_0
879-
stack << VarRef(Ident(local_name(insn[1], 0)))
880-
when :leave
881-
stack << ReturnNode(Args([stack.pop]))
882-
when :opt_and
883-
left, right = stack.pop(2)
884-
stack << Binary(left, :&, right)
885-
when :opt_div
886-
left, right = stack.pop(2)
887-
stack << Binary(left, :/, right)
888-
when :opt_eq
889-
left, right = stack.pop(2)
890-
stack << Binary(left, :==, right)
891-
when :opt_ge
892-
left, right = stack.pop(2)
893-
stack << Binary(left, :>=, right)
894-
when :opt_gt
895-
left, right = stack.pop(2)
896-
stack << Binary(left, :>, right)
897-
when :opt_le
898-
left, right = stack.pop(2)
899-
stack << Binary(left, :<=, right)
900-
when :opt_lt
901-
left, right = stack.pop(2)
902-
stack << Binary(left, :<, right)
903-
when :opt_ltlt
904-
left, right = stack.pop(2)
905-
stack << Binary(left, :<<, right)
906-
when :opt_minus
907-
left, right = stack.pop(2)
908-
stack << Binary(left, :-, right)
909-
when :opt_mod
910-
left, right = stack.pop(2)
911-
stack << Binary(left, :%, right)
912-
when :opt_mult
913-
left, right = stack.pop(2)
914-
stack << Binary(left, :*, right)
915-
when :opt_neq
916-
left, right = stack.pop(2)
917-
stack << Binary(left, :"!=", right)
918-
when :opt_or
919-
left, right = stack.pop(2)
920-
stack << Binary(left, :|, right)
921-
when :opt_plus
922-
left, right = stack.pop(2)
923-
stack << Binary(left, :+, right)
924-
when :opt_send_without_block
925-
receiver, *arguments = stack.pop(insn[1][:orig_argc] + 1)
926-
stack << CallNode(receiver, Period("."), Ident(insn[1][:mid]), ArgParen(Args(arguments)))
927-
when :putobject
928-
case insn[1]
929-
when Float
930-
stack << FloatLiteral(insn[1].inspect)
931-
when Integer
932-
stack << Int(insn[1].inspect)
933-
else
934-
raise "Unknown object type: #{insn[1].class.name}"
935-
end
936-
when :putobject_INT2FIX_0_
937-
stack << Int("0")
938-
when :putobject_INT2FIX_1_
939-
stack << Int("1")
940-
when :setlocal_WC_0
941-
stack << Assign(VarField(Ident(local_name(insn[1], 0))), stack.pop)
942-
else
943-
raise "Unknown instruction #{insn[0]}"
944-
end
945-
end
946-
947-
Program(Statements(stack))
948-
end
949-
950-
private
951-
952-
def local_name(index, level)
953-
current = iseq
954-
level.times { current = current.parent_iseq }
955-
current.local_table.locals[index].name.to_s
956-
end
957-
end
958-
959802
# These constants correspond to the putspecialobject instruction. They are
960803
# used to represent special objects that are pushed onto the stack.
961804
VM_SPECIAL_OBJECT_VMCORE = 1

0 commit comments

Comments
 (0)