/
compiler_test.rb
207 lines (164 loc) · 5.38 KB
/
compiler_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
require 'test_helper'
module Noscript
class CompilerTest < MiniTest::Unit::TestCase
def test_compile_integer_literal
assert_equal 1, compile("1")
end
def test_compile_unary_minus
assert_equal -1, compile("-1")
end
def test_compile_string_literal
assert_equal '1', compile("'1'")
end
def test_compile_string_literal_with_escaped_chars
assert_equal "\n", compile("'\n'")
end
def test_compile_string_interpolation
assert_equal '1', compile("'%s' % [1]")
end
def test_compile_string_interpolation_with_variables
assert_equal '1', compile("foo = 1; '%s' % foo")
end
def test_compile_assignment
assert_equal 1, compile("foo = 1; foo")
end
def test_compile_constant_assignment
assert_equal 1, compile("Foo = 1; Foo")
end
def test_compile_constant_lookup
assert_equal Rubinius, compile("Rubinius")
end
def test_compile_constant_lookup_with_namespace
assert_equal Noscript::AST::Identifier, compile("Noscript.AST.Identifier")
end
def test_compile_array_literal
assert_equal 1, compile("[1,2].at(0)")
end
def test_compile_array_literal_with_variables
assert_equal [3], compile("bar = 3; [bar]")
end
def test_compile_tuple_literal
assert_equal({'a' => true, 'b' => false}, compile("{a: true, b: false}"))
end
def test_compile_tuple_literal_referring_to_a_variable
assert_equal({'a' => 34, 'b' => false}, compile("foo = 34; {a: foo, b: false}"))
end
def test_compile_tuple_literal_inside_a_function
assert_equal({'a' => 34, 'b' => false}, compile("foo = -> bar; {a: bar, b: false}; end; foo(34)"))
end
def test_compile_tuple_literal_as_an_expression
assert_equal(['a', 'b'], compile("{a: true, b: false}.keys()"))
end
def test_compile_function_without_arguments
assert_equal 3, compile("foo = ->; 3; end; foo()")
end
def test_compile_function_with_unused_arguments
assert_equal 3, compile("foo = -> a; 3; end; foo(5)")
end
def test_compile_function_with_used_arguments
assert_equal 10, compile("foo = -> a; a + a; end; foo(5)")
end
def test_compile_function_with_call_inside
assert_equal 1, compile("foo = ->; '3'.length(); '3'.length(); end; foo()")
end
def test_compile_function_call_twice
assert_equal 3, compile("foo = ->; 3; end; '3'.length(); foo()")
end
def test_compile_function_call_twice_again
assert_equal 1, compile("'3'.length(); '3'.length()")
end
# TODO: Fix this
# def test_compile_function_scope
# assert_equal 3, compile(<<-CODE)
# hey = -> foo
# ho = -> bar
# foo + bar
# end
# ho(2)
# end
# hey(1)
# CODE
# end
def test_compile_multiple_expressions
result = compile("
if true != false
'3'
'3'
'3'
'3'
1
else
'3'
'3'
@errors.push('Expected to be truthy.')
end")
assert_equal 1, result
end
def test_compile_function_with_multiple_arguments
assert_equal 7, compile("foo = -> a, b, c; b + c; end; foo(5, 4, 3)")
end
def test_compile_function_as_an_object_slot
assert_equal 4, compile("foo = Object.clone(); foo.bar = ->; 4; end; foo.bar()")
end
def test_compile_true
assert_equal true, compile("true")
end
def test_compile_false
assert_equal false, compile("false")
end
def test_compile_nil
assert_equal nil, compile("nil")
end
def test_compile_call
assert_equal "1", compile("1.inspect()")
end
def test_compile_local_assign
assert_equal 3, compile("a = 3")
end
def test_compile_object_clone
obj = compile("Object.clone()")
assert_kind_of Object, obj
assert_equal Runtime::Object, obj.__noscript_prototype__
end
def test_compile_object_clone_with_properties
obj = compile("Object.clone({a: 1})")
assert_equal 1, obj.__noscript_get__(:a)
end
def test_compile_slot_get
assert_equal 1, compile("obj = Object.clone({a: 1}); obj.a")
end
def test_compile_slot_assign
obj = compile("foo = Object.clone(); foo.a = 3; foo")
assert_equal 3, obj.__noscript_get__(:a)
end
def test_compile_slot_assign_on_primitives
obj = compile("foo = 1; foo.a = 3; foo")
assert_equal 3, obj.__noscript_get__(:a)
end
def test_compile_if
assert_equal 1, compile("if true; 1; end")
end
def test_compile_if_else
assert_equal 2, compile("if false; 1; else; 2; end")
end
def test_compile_if_else_with_multiple_statements
assert_equal 7, compile("if false; 1 * 7; 2 + 33; 3; else; 2 + 4; 3 + 9; 4 + 3; end")
end
def test_compile_while
assert_equal 10, compile("a = 3; while a < 10; a = a + 1; end; a")
end
# Warning: this permanently pollutes self for the rest of the tests.
def test_self_equals_deref
assert_equal 3, compile("self.foo = 3; @foo")
end
# Warning: this permanently pollutes self for the rest of the tests.
def test_self_equals_deref_on_asignment
assert_equal 7, compile("@foo = 7; self.foo")
end
def test_ruby_call
identifier = compile("Noscript.AST.Identifier.ruby('new', 1, 'foo')")
assert_equal 1, identifier.line
assert_equal 'foo', identifier.name
end
end
end