rlang 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +3 -5
- data/README +11 -0
- data/bin/rlang +4 -0
- data/docs/RlangCompiler.md +2 -0
- data/docs/RlangManual.md +37 -8
- data/lib/rlang/lib/array/array32.rb +13 -4
- data/lib/rlang/lib/array/array64.rb +11 -3
- data/lib/rlang/lib/base64.rb +223 -0
- data/lib/rlang/lib/io.rb +7 -2
- data/lib/rlang/lib/malloc.rb +5 -3
- data/lib/rlang/lib/object.rb +23 -0
- data/lib/rlang/lib/rlang_core.rb +2 -1
- data/lib/rlang/lib/string.rb +95 -11
- data/lib/rlang/lib/type/i32.rb +30 -12
- data/lib/rlang/lib/type/i64.rb +0 -2
- data/lib/rlang/lib/wasi.rb +57 -6
- data/lib/rlang/parser/data.rb +5 -0
- data/lib/rlang/parser/ext/integer.rb +3 -1
- data/lib/rlang/parser/ext/type.rb +30 -1
- data/lib/rlang/parser/global.rb +7 -0
- data/lib/rlang/parser/wgenerator.rb +221 -83
- data/lib/rlang/parser/wnode.rb +41 -14
- data/lib/rlang/parser/wtype.rb +12 -6
- data/lib/rlang/parser.rb +182 -130
- data/lib/rlang/version.rb +1 -1
- data/lib/ruby/mirror/rstring.rb +16 -0
- data/lib/utils/exceptions.rb +12 -0
- data/rlang.gemspec +4 -4
- metadata +16 -12
data/lib/rlang/parser.rb
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
require 'parser/current'
|
14
14
|
require 'pathname'
|
15
15
|
require_relative '../utils/log'
|
16
|
+
require_relative '../utils/exceptions'
|
16
17
|
require_relative './parser/wtype'
|
17
18
|
require_relative './parser/wtree'
|
18
19
|
require_relative './parser/wnode'
|
@@ -77,7 +78,7 @@ module Rlang::Parser
|
|
77
78
|
# Note : this method can be called recursively
|
78
79
|
# through require statements
|
79
80
|
def parse_file(file)
|
80
|
-
|
81
|
+
rlse node, "parse_file only acccepts absolute path (got #{file})" \
|
81
82
|
unless Pathname.new(file).absolute? || file.nil?
|
82
83
|
# Already parsed. Ignore.
|
83
84
|
if self.config[:LOADED_FEATURES].include? file
|
@@ -103,7 +104,14 @@ module Rlang::Parser
|
|
103
104
|
end
|
104
105
|
|
105
106
|
def parse(source, wnode=nil)
|
106
|
-
|
107
|
+
if config[:comments]
|
108
|
+
ast, comments = ::Parser::CurrentRuby.parse_with_comments(source)
|
109
|
+
@associated_comments = ::Parser::Source::Comment.associate(ast, comments)
|
110
|
+
else
|
111
|
+
ast = ::Parser::CurrentRuby.parse(source)
|
112
|
+
@associated_comments = {}
|
113
|
+
end
|
114
|
+
|
107
115
|
parse_node(ast, wnode || @wgenerator.root) if ast
|
108
116
|
end
|
109
117
|
|
@@ -114,11 +122,16 @@ module Rlang::Parser
|
|
114
122
|
# - keep_eval: whether to keep the value of the evaluated
|
115
123
|
# WAT expression on stock or not
|
116
124
|
def parse_node(node, wnode, keep_eval=true)
|
117
|
-
|
125
|
+
rlse node, "wnode type is incorrect (got #{wnode})" unless wnode.is_a?(WNode) || wnode.nil?
|
118
126
|
logger.debug "\n---------------------->>\n" +
|
119
127
|
"Parsing node: #{node}, wnode: #{wnode.head}, keep_eval: #{keep_eval}"
|
120
128
|
# Nothing to parse
|
121
|
-
return if node.nil?
|
129
|
+
return if node.nil?
|
130
|
+
|
131
|
+
# check if there is a comment
|
132
|
+
if config[:comments] && (comments = @associated_comments[node])
|
133
|
+
@wgenerator.comments(wnode, comments)
|
134
|
+
end
|
122
135
|
|
123
136
|
case node.type
|
124
137
|
when :self
|
@@ -173,11 +186,11 @@ module Rlang::Parser
|
|
173
186
|
wn = parse_int(node, wnode, keep_eval)
|
174
187
|
|
175
188
|
when :float
|
176
|
-
|
189
|
+
rlse node, "float instructions not supported"
|
177
190
|
#parse_float(node, wnode, keep_eval)
|
178
191
|
|
179
192
|
when :nil
|
180
|
-
|
193
|
+
rlse node, "nil not supported"
|
181
194
|
|
182
195
|
when :const
|
183
196
|
wn = parse_const(node, wnode, keep_eval)
|
@@ -218,10 +231,13 @@ module Rlang::Parser
|
|
218
231
|
when :str
|
219
232
|
wn = parse_string(node, wnode, keep_eval)
|
220
233
|
|
234
|
+
when :array
|
235
|
+
wn = parse_array(node, wnode, keep_eval)
|
236
|
+
|
221
237
|
else
|
222
|
-
|
238
|
+
rlse node, "Unknown node type: #{node.type} => #{node}"
|
223
239
|
end
|
224
|
-
|
240
|
+
rlse node, "wnode type is incorrect (got #{wn}) at node #{node}" unless wn.is_a?(WNode) || wn.nil?
|
225
241
|
logger.debug "\n----------------------<<\n" +
|
226
242
|
"End parsing node: #{node}, parent wnode: #{wnode&.head}, keep_eval: #{keep_eval}\n generated wnode #{wn&.head}" +
|
227
243
|
"\n----------------------<<\n"
|
@@ -264,7 +280,7 @@ module Rlang::Parser
|
|
264
280
|
# (const nil :Stack) (const nil :Array) (begin ....)))
|
265
281
|
def parse_class(node, wnode)
|
266
282
|
class_const_node, super_class_const_node, body_node = *node.children
|
267
|
-
|
283
|
+
rlse node, "expecting a constant for class name (got #{const_node})" \
|
268
284
|
unless class_const_node.type == :const
|
269
285
|
|
270
286
|
# create the class wnode
|
@@ -301,7 +317,7 @@ module Rlang::Parser
|
|
301
317
|
def parse_module(node, wnode)
|
302
318
|
const_node = node.children.first
|
303
319
|
body_node = node.children.last
|
304
|
-
|
320
|
+
rlse node, "expecting a constant for module name (got #{const_node})" \
|
305
321
|
unless const_node.type == :const
|
306
322
|
|
307
323
|
module_path = _build_const_path(const_node)
|
@@ -376,7 +392,8 @@ module Rlang::Parser
|
|
376
392
|
# wnode as a child of wnode
|
377
393
|
wn_var_set = parse_node(var_asgn_node, wnode, keep_eval)
|
378
394
|
gvar = Global.find(var_name)
|
379
|
-
|
395
|
+
# \nline #{node.location.line}: #{node.location.expression.range.source}
|
396
|
+
rlse node, "Unknown global variable #{var_name}" unless gvar
|
380
397
|
|
381
398
|
# Create the operator node (infer operator type from variable)
|
382
399
|
wn_op = @wgenerator.send_method(wn_var_set, gvar.wtype.class_path, op, :instance)
|
@@ -393,7 +410,7 @@ module Rlang::Parser
|
|
393
410
|
# wnode as a child of wnode
|
394
411
|
wn_var_set = parse_node(var_asgn_node, wnode, keep_eval)
|
395
412
|
cvar = wnode.find_cvar(var_name)
|
396
|
-
|
413
|
+
rlse node, "Unknown class variable #{var_name}" unless cvar
|
397
414
|
|
398
415
|
# Create the operator node (infer operator type from variable)
|
399
416
|
wn_op = @wgenerator.send_method(wn_var_set, cvar.wtype.class_path, op, :instance)
|
@@ -410,7 +427,7 @@ module Rlang::Parser
|
|
410
427
|
# wnode as a child of wnode
|
411
428
|
wn_var_set = parse_node(var_asgn_node, wnode, keep_eval)
|
412
429
|
lvar = wnode.find_lvar(var_name) || wnode.find_marg(var_name)
|
413
|
-
|
430
|
+
rlse node, "Unknown local variable #{var_name}" unless lvar
|
414
431
|
|
415
432
|
# Create the operator node (infer operator type from variable)
|
416
433
|
wn_op = @wgenerator.send_method(wn_var_set, lvar.wtype.class_path, op, :instance)
|
@@ -424,14 +441,14 @@ module Rlang::Parser
|
|
424
441
|
# s(:op_asgn,
|
425
442
|
# s(:ivasgn, :@stack_ptr), :-, s(:lvar, :nbytes))
|
426
443
|
when :ivasgn
|
427
|
-
|
444
|
+
rlse node, "Instance variable can only be accessed in instance method scope" \
|
428
445
|
unless wnode.in_instance_method_scope?
|
429
446
|
var_asgn_node, operator, exp_node = *node.children
|
430
447
|
var_name = var_asgn_node.children.last
|
431
448
|
|
432
449
|
# To op_asgn to work, ivar must already be declared
|
433
450
|
ivar = wnode.find_ivar(var_name)
|
434
|
-
|
451
|
+
rlse node, "Unknown instance variable #{var_name}" unless ivar
|
435
452
|
|
436
453
|
# Create the top level variable setter node
|
437
454
|
wn_var_set = @wgenerator.ivasgn(wnode, ivar)
|
@@ -493,7 +510,7 @@ module Rlang::Parser
|
|
493
510
|
#@wgenerator.send_method(wnode, wn_recv.wtype.class_path, "#{method_name}", :instance)
|
494
511
|
end
|
495
512
|
else
|
496
|
-
|
513
|
+
rlse node, "op_asgn not supported for #{node.children.first}"
|
497
514
|
end
|
498
515
|
|
499
516
|
# Finally, parse the expression node and make it
|
@@ -516,9 +533,9 @@ module Rlang::Parser
|
|
516
533
|
class_path_node, constant_name, exp_node = *node.children
|
517
534
|
const_path = _build_const_path(class_path_node) << constant_name
|
518
535
|
|
519
|
-
#
|
536
|
+
# rlse node, "dynamic constant assignment" unless wnode.in_class_scope?
|
520
537
|
# unless class_path_node.nil?
|
521
|
-
#
|
538
|
+
# rlse node, "constant assignment with class path not supported (got #{class_name_node})"
|
522
539
|
# end
|
523
540
|
|
524
541
|
# find the scope class
|
@@ -543,10 +560,10 @@ module Rlang::Parser
|
|
543
560
|
wn_casgn = @wgenerator.casgn(wnode, const)
|
544
561
|
wn_exp = parse_node(exp_node, wn_casgn)
|
545
562
|
@wgenerator.cast(wn_exp, const.wtype, false)
|
546
|
-
logger.
|
563
|
+
logger.warn "Already initialized constant #{const.name}"
|
547
564
|
end
|
548
565
|
else
|
549
|
-
|
566
|
+
rlse node, "Constant #{const_path} not declared before" unless const
|
550
567
|
wn_casgn = @wgenerator.casgn(wnode, const)
|
551
568
|
end
|
552
569
|
# to mimic Ruby push the constant value on stack if needed
|
@@ -561,7 +578,7 @@ module Rlang::Parser
|
|
561
578
|
# executing this code. Just statically initiliazing the
|
562
579
|
# const with the value
|
563
580
|
wn_exp = parse_node(exp_node, wnode)
|
564
|
-
|
581
|
+
rlse node, "Constant initializer can only be an int or a constant/class (got #{wn_exp}" \
|
565
582
|
unless wn_exp.const?
|
566
583
|
if (const = wnode.find_const(const_path))
|
567
584
|
logger.warn "already initialized constant #{const.path}"
|
@@ -574,7 +591,7 @@ module Rlang::Parser
|
|
574
591
|
logger.debug "Constant #{const_path} initialized with value #{const.value} and wtype #{const.wtype}"
|
575
592
|
return nil
|
576
593
|
else
|
577
|
-
|
594
|
+
rlse node, "Constant can only be defined in method or class scope"
|
578
595
|
end
|
579
596
|
end
|
580
597
|
|
@@ -614,7 +631,7 @@ module Rlang::Parser
|
|
614
631
|
@wgenerator.cast(wn_exp, gvar.wtype, false)
|
615
632
|
end
|
616
633
|
else
|
617
|
-
|
634
|
+
rlse node, "Global variable #{gv_name} not declared before" unless gvar
|
618
635
|
wn_gvasgn = @wgenerator.gvasgn(wnode, gvar)
|
619
636
|
end
|
620
637
|
# to mimic Ruby push the variable value on stack if needed
|
@@ -623,7 +640,7 @@ module Rlang::Parser
|
|
623
640
|
elsif true #wnode.in_class_scope?
|
624
641
|
# If we are at root or in class scope
|
625
642
|
# then it is a global variable initialization
|
626
|
-
|
643
|
+
rlse node, "Global op_asgn can only happen in method scope" unless exp_node
|
627
644
|
# In the class or root scope
|
628
645
|
# it can only be a Global var **declaration**
|
629
646
|
# In this case the expression has to reduce
|
@@ -633,7 +650,7 @@ module Rlang::Parser
|
|
633
650
|
# Then remove the generated wnode because it is not for
|
634
651
|
# execution. It is just to get the init value
|
635
652
|
wn_exp = parse_node(exp_node, wnode)
|
636
|
-
|
653
|
+
rlse node, "Global initializer can only be a int or a constant/class (got #{wn_exp})" \
|
637
654
|
unless wn_exp.const?
|
638
655
|
wnode.remove_child(wn_exp)
|
639
656
|
if gvar
|
@@ -645,7 +662,7 @@ module Rlang::Parser
|
|
645
662
|
#gvar.export! if self.config[:export_all]
|
646
663
|
return nil
|
647
664
|
else
|
648
|
-
|
665
|
+
rlse node, "Global can only be defined in method or class scope"
|
649
666
|
end
|
650
667
|
end
|
651
668
|
|
@@ -657,7 +674,7 @@ module Rlang::Parser
|
|
657
674
|
def parse_ivasgn(node, wnode, keep_eval)
|
658
675
|
iv_name, exp_node = *node.children
|
659
676
|
|
660
|
-
|
677
|
+
rlse node, "Instance variable #{iv_name} can only used in instance method scope" \
|
661
678
|
unless wnode.in_instance_method_scope?
|
662
679
|
|
663
680
|
if (ivar = wnode.find_ivar(iv_name))
|
@@ -715,7 +732,7 @@ module Rlang::Parser
|
|
715
732
|
@wgenerator.cast(wn_exp, cvar.wtype, false)
|
716
733
|
end
|
717
734
|
else
|
718
|
-
|
735
|
+
rlse node, "Class variable #{cv_name} not declared before" unless cvar
|
719
736
|
wn_cvasgn = @wgenerator.cvasgn(wnode, cvar)
|
720
737
|
end
|
721
738
|
# to mimic Ruby push the variable value on stack if needed
|
@@ -725,14 +742,14 @@ module Rlang::Parser
|
|
725
742
|
elsif wnode.in_class_scope?
|
726
743
|
# If we are in class scope
|
727
744
|
# then it is a class variable initialization
|
728
|
-
|
729
|
-
|
745
|
+
rlse node, "Class variable #{cv_name} already declared" if cvar
|
746
|
+
rlse node, "Class variable op_asgn can only happen in method scope" unless exp_node
|
730
747
|
# Parse the expression node to see if it's a ixx.const
|
731
748
|
# in the end but get rid of it then because we are not
|
732
749
|
# executing this code. Just statically initiliazing the
|
733
750
|
# cvar with the value
|
734
751
|
wn_exp = parse_node(exp_node, wnode)
|
735
|
-
|
752
|
+
rlse node, "Class variable initializer can only be an int or a constant/class (got #{wn_exp}" \
|
736
753
|
unless wn_exp.const?
|
737
754
|
cvar = wnode.create_cvar(cv_name, wn_exp.wargs[:value], wn_exp.wtype)
|
738
755
|
wnode.remove_child(wn_exp)
|
@@ -740,7 +757,7 @@ module Rlang::Parser
|
|
740
757
|
return
|
741
758
|
|
742
759
|
else
|
743
|
-
|
760
|
+
rlse node, "Class variable can only be defined in method or class scope"
|
744
761
|
end
|
745
762
|
end
|
746
763
|
|
@@ -778,7 +795,7 @@ module Rlang::Parser
|
|
778
795
|
@wgenerator.cast(wn_exp, lvar.wtype, false)
|
779
796
|
end
|
780
797
|
else
|
781
|
-
|
798
|
+
rlse node, "Local variable #{cv_name} not declared before" unless lvar
|
782
799
|
wn_lvasgn = @wgenerator.lvasgn(wnode, lvar)
|
783
800
|
end
|
784
801
|
# to mimic Ruby push the variable value on stack if needed
|
@@ -793,7 +810,7 @@ module Rlang::Parser
|
|
793
810
|
def parse_gvar(node, wnode, keep_eval)
|
794
811
|
gv_name, = *node.children
|
795
812
|
gvar = Global.find(gv_name)
|
796
|
-
|
813
|
+
rlse node, "Unknown Global variable #{gv_name}" unless gvar
|
797
814
|
wn_gvar = @wgenerator.gvar(wnode, gvar)
|
798
815
|
# Drop last evaluated result if asked to
|
799
816
|
@wgenerator.drop(wnode) unless keep_eval
|
@@ -805,13 +822,13 @@ module Rlang::Parser
|
|
805
822
|
# ---
|
806
823
|
# ... s(:ivar, :@stack_ptr)
|
807
824
|
def parse_ivar(node, wnode, keep_eval)
|
808
|
-
|
825
|
+
rlse node, "Instance variable can only be accessed in instance method scope" \
|
809
826
|
unless wnode.in_instance_method_scope?
|
810
827
|
iv_name, = *node.children
|
811
828
|
if (ivar = wnode.find_ivar(iv_name))
|
812
829
|
wn_ivar = @wgenerator.ivar(wnode, ivar)
|
813
830
|
else
|
814
|
-
|
831
|
+
rlse node, "unknown instance variable #{ivar_name}"
|
815
832
|
end
|
816
833
|
# Drop last evaluated result if asked to
|
817
834
|
@wgenerator.drop(wnode) unless keep_eval
|
@@ -823,13 +840,13 @@ module Rlang::Parser
|
|
823
840
|
# ---
|
824
841
|
# ... s(:cvar, :@@stack_ptr)
|
825
842
|
def parse_cvar(node, wnode, keep_eval)
|
826
|
-
|
843
|
+
rlse node, "Class variable can only be accessed in method scope" \
|
827
844
|
unless wnode.in_method_scope?
|
828
845
|
cv_name, = *node.children
|
829
846
|
if (cvar = wnode.find_cvar(cv_name))
|
830
847
|
wn_cvar = @wgenerator.cvar(wnode, cvar)
|
831
848
|
else
|
832
|
-
|
849
|
+
rlse node, "unknown class variable #{cv_name}"
|
833
850
|
end
|
834
851
|
# Drop last evaluated result if asked to
|
835
852
|
@wgenerator.drop(wnode) unless keep_eval
|
@@ -847,7 +864,7 @@ module Rlang::Parser
|
|
847
864
|
if (lvar = wnode.find_lvar(lv_name) || wnode.find_marg(lv_name))
|
848
865
|
wn_lvar = @wgenerator.lvar(wnode, lvar)
|
849
866
|
else
|
850
|
-
|
867
|
+
rlse node, "unknown local variable #{lv_name}"
|
851
868
|
end
|
852
869
|
# Drop last evaluated result if asked to
|
853
870
|
@wgenerator.drop(wnode) unless keep_eval
|
@@ -883,12 +900,11 @@ module Rlang::Parser
|
|
883
900
|
return wn_false
|
884
901
|
end
|
885
902
|
|
886
|
-
#
|
887
|
-
# in
|
888
|
-
#
|
889
|
-
#
|
890
|
-
#
|
891
|
-
# we must instantiate a dynamic string object
|
903
|
+
# When a string literal initializer is used
|
904
|
+
# in root or class scope, the string literal is
|
905
|
+
# allocated statically.
|
906
|
+
# If the initializer is used in a method scope
|
907
|
+
# we instantiate a dynamic string object
|
892
908
|
# and copy the initial static value in it
|
893
909
|
def parse_string(node, wnode, keep_eval)
|
894
910
|
string = node.children.last
|
@@ -906,6 +922,45 @@ module Rlang::Parser
|
|
906
922
|
return wn_string
|
907
923
|
end
|
908
924
|
|
925
|
+
# Example
|
926
|
+
# [1, -2, 5]
|
927
|
+
# -------
|
928
|
+
# (array
|
929
|
+
# (int 1)
|
930
|
+
# (int -2)
|
931
|
+
# (int 5)
|
932
|
+
# )
|
933
|
+
#
|
934
|
+
# When an array literal initializer is used
|
935
|
+
# in root or class scope, the array literal is
|
936
|
+
# allocated statically.
|
937
|
+
# If the initializer is used in a method scope
|
938
|
+
# we instantiate a dynamic string object
|
939
|
+
# and copy the initial static value in it
|
940
|
+
#
|
941
|
+
def parse_array(node, wnode, keep_eval)
|
942
|
+
# check that all array elements are of type int
|
943
|
+
# this is the only initializer type we support for
|
944
|
+
# now. Collect int values.
|
945
|
+
array = node.children.collect do |wn|
|
946
|
+
rlse node, "Array initializer can only be of type int (got #{wn}" unless wn.type == :int
|
947
|
+
wn.children.last
|
948
|
+
end
|
949
|
+
|
950
|
+
if wnode.in_method_scope?
|
951
|
+
# allocate array dynamically
|
952
|
+
wn_array = @wgenerator.array_dynamic_new(wnode, array)
|
953
|
+
else
|
954
|
+
# allocate array statically
|
955
|
+
wn_array = @wgenerator.array_static_new(wnode, array)
|
956
|
+
end
|
957
|
+
# Drop last evaluated result if asked to
|
958
|
+
@wgenerator.drop(wnode) unless keep_eval
|
959
|
+
|
960
|
+
logger.debug "wn_array:#{wn_array} wtype:#{wn_array.wtype} keep_eval:#{keep_eval}"
|
961
|
+
return wn_array
|
962
|
+
end
|
963
|
+
|
909
964
|
# Example
|
910
965
|
# TestA::C::MYCONST
|
911
966
|
# -------
|
@@ -917,7 +972,7 @@ module Rlang::Parser
|
|
917
972
|
|
918
973
|
# See if constant exists. It should at this point
|
919
974
|
unless (const = wnode.find_const(const_path))
|
920
|
-
|
975
|
+
rlse node, "unknown constant #{full_const_name}"
|
921
976
|
end
|
922
977
|
wn_const = @wgenerator.const(wnode, const)
|
923
978
|
|
@@ -930,7 +985,7 @@ module Rlang::Parser
|
|
930
985
|
def parse_args(node, wnode)
|
931
986
|
# collect method arguments
|
932
987
|
node.children.each do |arg_node|
|
933
|
-
|
988
|
+
rlse node, "only regular method argument is supported (got #{arg_node.type})" if arg_node.type != :arg
|
934
989
|
# keep track of method arguments. Do not generate wasm code yet
|
935
990
|
# as 'arg' directives may later affect argument types (see parse_send)
|
936
991
|
wnode.create_marg(arg_node.children.last)
|
@@ -956,7 +1011,7 @@ module Rlang::Parser
|
|
956
1011
|
recv_node = nil
|
957
1012
|
else
|
958
1013
|
recv_node, method_name, arg_nodes, body_node = *node.children
|
959
|
-
|
1014
|
+
rlse node, "only class method is supported. Wrong receiver at #{recv_node.loc.expression}" \
|
960
1015
|
if recv_node.type != :self
|
961
1016
|
end
|
962
1017
|
logger.debug "Defining class method: #{method_name}"
|
@@ -1102,7 +1157,7 @@ module Rlang::Parser
|
|
1102
1157
|
end
|
1103
1158
|
end
|
1104
1159
|
end
|
1105
|
-
|
1160
|
+
rlse node, LoadError, "no such file to load: #{file}" unless full_path_file
|
1106
1161
|
|
1107
1162
|
# Now load the file
|
1108
1163
|
if File.extname(full_path_file) == '.wat'
|
@@ -1203,22 +1258,22 @@ module Rlang::Parser
|
|
1203
1258
|
case method_name
|
1204
1259
|
when :address=
|
1205
1260
|
value_node = node.children[2]
|
1206
|
-
|
1261
|
+
rlse node, "DAta address must be an integer" unless value_node.type == :int
|
1207
1262
|
DAta.address = value_node.children.last
|
1208
1263
|
when :align
|
1209
1264
|
value_node = node.children[2]
|
1210
|
-
|
1265
|
+
rlse node, "DAta alignment argument must be an integer" unless value_node.type == :int
|
1211
1266
|
DAta.align(value_node.children.last)
|
1212
1267
|
when :[]=
|
1213
1268
|
if (data_label_node = node.children[2]).type == :sym
|
1214
1269
|
label = data_label_node.children.last
|
1215
1270
|
else
|
1216
|
-
|
1271
|
+
rlse node, "Data label must be a symbol (got #{data_label_node}"
|
1217
1272
|
end
|
1218
1273
|
arg_node = node.children[3]
|
1219
1274
|
parse_data_value(label, arg_node)
|
1220
1275
|
else
|
1221
|
-
|
1276
|
+
rlse node, "Unsupported DAta method #{method_name}"
|
1222
1277
|
end
|
1223
1278
|
return
|
1224
1279
|
end
|
@@ -1231,7 +1286,7 @@ module Rlang::Parser
|
|
1231
1286
|
# Example
|
1232
1287
|
# (expression).cast_to(class_name, argument)
|
1233
1288
|
# -----
|
1234
|
-
# s(:
|
1289
|
+
# s(:send,
|
1235
1290
|
# s(expression),
|
1236
1291
|
# :cast_to, s(sym, :Class_name))
|
1237
1292
|
# the signed argument true|false is optional and
|
@@ -1239,7 +1294,7 @@ module Rlang::Parser
|
|
1239
1294
|
# Class_name is a symbol like :A or :"A:B" or :"A:B:C"
|
1240
1295
|
if method_name == :cast_to
|
1241
1296
|
class_name_node = node.children.last
|
1242
|
-
|
1297
|
+
rlse node, "cast_to expects a symbol argument (got #{class_name_node}" unless class_name_node.type == :sym
|
1243
1298
|
tgt_wtype = WType.new(class_name_node.children.first)
|
1244
1299
|
logger.debug "in cast_to: target type #{tgt_wtype}"
|
1245
1300
|
|
@@ -1254,26 +1309,23 @@ module Rlang::Parser
|
|
1254
1309
|
end
|
1255
1310
|
|
1256
1311
|
|
1257
|
-
#
|
1258
|
-
#
|
1259
|
-
#
|
1312
|
+
# Explicit type cast directives for native types.
|
1313
|
+
# Used at compile time
|
1314
|
+
#
|
1260
1315
|
# Example
|
1261
|
-
# (recv).
|
1316
|
+
# (recv).to_xxxx where xxxx can be [U]I[32|64]
|
1262
1317
|
# -----
|
1263
|
-
# s(:
|
1318
|
+
# s(:send,
|
1264
1319
|
# s(expression),
|
1265
|
-
# :to_I64
|
1266
|
-
#
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
if (cnt = node.children.count) == 3
|
1271
|
-
signed = true if node.children.last.type == :true
|
1272
|
-
elsif cnt == 2
|
1273
|
-
signed = false
|
1274
|
-
else
|
1275
|
-
raise "cast directive should have 0 or 1 argument (got #{cnt - 2})"
|
1320
|
+
# :to_I64)
|
1321
|
+
#
|
1322
|
+
if [:to_UI64, :to_I64, :to_UI32, :to_I32].include? method_name
|
1323
|
+
if (cnt = node.children.count) > 2
|
1324
|
+
rlse node, "cast directive should have no argument (got #{cnt - 2})"
|
1276
1325
|
end
|
1326
|
+
tgt_rlang_type = method_name.to_s.scan(/to_(.+)$/).first.first
|
1327
|
+
tgt_wtype = WType.new(tgt_rlang_type)
|
1328
|
+
signed = tgt_wtype.signed?
|
1277
1329
|
logger.debug "in cast section: child count #{cnt}, tgt_wtype #{tgt_wtype}, signed: #{signed}"
|
1278
1330
|
|
1279
1331
|
# Parse the expression and cast it
|
@@ -1303,7 +1355,7 @@ module Rlang::Parser
|
|
1303
1355
|
|
1304
1356
|
# See if constant exists. It should at this point
|
1305
1357
|
unless (const = wnode.find_const(const_path))
|
1306
|
-
|
1358
|
+
rlse node, "unknown constant #{full_const_name}"
|
1307
1359
|
end
|
1308
1360
|
wn_const_addr = @wgenerator.const_addr(wnode, const)
|
1309
1361
|
|
@@ -1312,13 +1364,13 @@ module Rlang::Parser
|
|
1312
1364
|
return wn_const_addr
|
1313
1365
|
|
1314
1366
|
elsif recv_node.type == :cvar
|
1315
|
-
|
1367
|
+
rlse node, "Class variable can only be accessed in method scope" \
|
1316
1368
|
unless wnode.in_method_scope?
|
1317
1369
|
cv_name = recv_node.children.first
|
1318
1370
|
if (cvar = wnode.find_cvar(cv_name))
|
1319
1371
|
wn_cvar_addr = @wgenerator.cvar_addr(wnode, cvar)
|
1320
1372
|
else
|
1321
|
-
|
1373
|
+
rlse node, "unknown class variable #{cv_name}"
|
1322
1374
|
end
|
1323
1375
|
# Drop last evaluated result if asked to
|
1324
1376
|
@wgenerator.drop(wnode) unless keep_eval
|
@@ -1338,7 +1390,7 @@ module Rlang::Parser
|
|
1338
1390
|
def parse_send_nil_receiver(node, wnode, keep_eval)
|
1339
1391
|
recv_node = node.children[0]
|
1340
1392
|
method_name = node.children[1]
|
1341
|
-
|
1393
|
+
rlse node, "receiver should be nil here (got #{recv_node})" \
|
1342
1394
|
unless recv_node.nil?
|
1343
1395
|
|
1344
1396
|
if recv_node.nil? && method_name == :require
|
@@ -1402,10 +1454,10 @@ module Rlang::Parser
|
|
1402
1454
|
# (send nil :require
|
1403
1455
|
# (str "test5"))
|
1404
1456
|
def parse_send_require(node, wnode, keep_eval)
|
1405
|
-
|
1457
|
+
rlse node, "require must be used at root level" \
|
1406
1458
|
unless wnode.in_root_scope?
|
1407
1459
|
file_node = node.children.last
|
1408
|
-
|
1460
|
+
rlse node, "require only accepts a string argument (got #{file_node})" \
|
1409
1461
|
unless file_node.type == :str
|
1410
1462
|
parse_require(wnode, file_node.children.last)
|
1411
1463
|
return
|
@@ -1417,10 +1469,10 @@ module Rlang::Parser
|
|
1417
1469
|
# (send nil :require_relative
|
1418
1470
|
# (str "test5"))
|
1419
1471
|
def parse_send_require_relative(node, wnode, keep_eval)
|
1420
|
-
|
1472
|
+
rlse node, "require_relative must be used at root level" \
|
1421
1473
|
unless wnode.in_root_scope?
|
1422
1474
|
file_node = node.children.last
|
1423
|
-
|
1475
|
+
rlse node, "require only accepts a string argument (got #{file_node})" \
|
1424
1476
|
unless file_node.type == :str
|
1425
1477
|
parse_require_relative(wnode, file_node.children.last)
|
1426
1478
|
return
|
@@ -1436,9 +1488,9 @@ module Rlang::Parser
|
|
1436
1488
|
def parse_send_include(node, wnode, keep_eval)
|
1437
1489
|
const_node = node.children.last
|
1438
1490
|
module_path = _build_const_path(const_node)
|
1439
|
-
|
1491
|
+
rlse node, "expecting a constant for include (got #{const_node})" \
|
1440
1492
|
unless const_node.type == :const
|
1441
|
-
|
1493
|
+
rlse node, "include must be used in class scope" \
|
1442
1494
|
unless wnode.in_class_scope?
|
1443
1495
|
@wgenerator.include(wnode, module_path)
|
1444
1496
|
end
|
@@ -1453,9 +1505,9 @@ module Rlang::Parser
|
|
1453
1505
|
def parse_send_prepend(node, wnode, keep_eval)
|
1454
1506
|
const_node = node.children.last
|
1455
1507
|
module_path = _build_const_path(const_node)
|
1456
|
-
|
1508
|
+
rlse node, "expecting a constant for prepend (got #{const_node})" \
|
1457
1509
|
unless const_node.type == :const
|
1458
|
-
|
1510
|
+
rlse node, "prepend must be used in class scope" \
|
1459
1511
|
unless wnode.in_class_scope?
|
1460
1512
|
@wgenerator.prepend(wnode, module_path)
|
1461
1513
|
end
|
@@ -1470,9 +1522,9 @@ module Rlang::Parser
|
|
1470
1522
|
def parse_send_extend(node, wnode, keep_eval)
|
1471
1523
|
const_node = node.children.last
|
1472
1524
|
module_path = _build_const_path(const_node)
|
1473
|
-
|
1525
|
+
rlse node, "expecting a constant for extend (got #{const_node})" \
|
1474
1526
|
unless const_node.type == :const
|
1475
|
-
|
1527
|
+
rlse node, "extend must be used in class scope" \
|
1476
1528
|
unless wnode.in_class_scope?
|
1477
1529
|
@wgenerator.extend(wnode, module_path)
|
1478
1530
|
end
|
@@ -1494,10 +1546,10 @@ module Rlang::Parser
|
|
1494
1546
|
# will be automatically built from the class/method names
|
1495
1547
|
def parse_send_export(node, wnode, keep_eval)
|
1496
1548
|
logger.debug "Export directive found for..."
|
1497
|
-
|
1549
|
+
rlse node, "export must be used in class scope" unless wnode.in_class_or_module_scope?
|
1498
1550
|
@@export = true
|
1499
1551
|
if (function_node = node.children[2])
|
1500
|
-
|
1552
|
+
rlse node, "export function name must be a symbol (got #{function_node})" \
|
1501
1553
|
unless function_node.type == :sym
|
1502
1554
|
@@export_name = function_node.children.last
|
1503
1555
|
end
|
@@ -1517,14 +1569,14 @@ module Rlang::Parser
|
|
1517
1569
|
#
|
1518
1570
|
def parse_send_import(node, wnode, keep_eval)
|
1519
1571
|
logger.debug "Import directive found for..."
|
1520
|
-
|
1521
|
-
|
1572
|
+
rlse node, "export must be used in class scope" unless wnode.in_class_or_module_scope?
|
1573
|
+
rlse node, "import expects 2 arguments (got #{node.children.count - 2})" \
|
1522
1574
|
unless node.children.count == 4
|
1523
1575
|
|
1524
1576
|
module_node, function_node = node.children[2..-1]
|
1525
|
-
|
1577
|
+
rlse node, "import module name must be a symbol (got #{module_node})" \
|
1526
1578
|
unless module_node.type == :sym
|
1527
|
-
|
1579
|
+
rlse node, "import function name must be a symbol (got #{function_node})" \
|
1528
1580
|
unless function_node.type == :sym
|
1529
1581
|
@@import = true
|
1530
1582
|
@@import_module_name = module_node.children.last
|
@@ -1546,13 +1598,13 @@ module Rlang::Parser
|
|
1546
1598
|
# s(:sym, :I64))
|
1547
1599
|
# ))
|
1548
1600
|
def parse_send_local(node, wnode, keep_eval)
|
1549
|
-
|
1601
|
+
rlse node, "local declaration can only be used in methods" \
|
1550
1602
|
unless wnode.in_method_scope?
|
1551
1603
|
hash_node = node.children.last
|
1552
1604
|
local_types = parse_type_args(hash_node, :local)
|
1553
1605
|
local_types.each do |name, wtype|
|
1554
1606
|
lvar = wnode.find_or_create_lvar(name)
|
1555
|
-
|
1607
|
+
rlse node, "couldn't find or create local variable #{name}" unless lvar
|
1556
1608
|
lvar.wtype = WType.new(wtype)
|
1557
1609
|
end
|
1558
1610
|
return
|
@@ -1571,13 +1623,13 @@ module Rlang::Parser
|
|
1571
1623
|
# s(:sym, :I64))
|
1572
1624
|
# ))
|
1573
1625
|
def parse_send_arg(node, wnode, keep_eval)
|
1574
|
-
|
1626
|
+
rlse node, "arg declaration can only be used in methods" \
|
1575
1627
|
unless wnode.in_method_scope?
|
1576
1628
|
hash_node = node.children.last
|
1577
1629
|
marg_types = parse_type_args(hash_node, :argument)
|
1578
1630
|
marg_types.each do |name, wtype|
|
1579
1631
|
marg = wnode.find_marg(name)
|
1580
|
-
|
1632
|
+
rlse node, "couldn't find method argument #{name}" unless marg
|
1581
1633
|
marg.wtype = WType.new(wtype)
|
1582
1634
|
end
|
1583
1635
|
return
|
@@ -1621,7 +1673,7 @@ module Rlang::Parser
|
|
1621
1673
|
def parse_send_result(node, wnode, keep_eval)
|
1622
1674
|
if wnode.in_method_scope?
|
1623
1675
|
result_type, = *node.children[2]
|
1624
|
-
|
1676
|
+
rlse node, "result directive expects a symbol argument (got #{result_type})" \
|
1625
1677
|
unless result_type.is_a? Symbol
|
1626
1678
|
wnode.method_wnode.wtype = WType.new(result_type)
|
1627
1679
|
logger.debug "result_type #{result_type} updated for method #{wnode.method_wnode.method}"
|
@@ -1629,11 +1681,11 @@ module Rlang::Parser
|
|
1629
1681
|
class_path_name, = *node.children[2]
|
1630
1682
|
method_name, = *node.children[3]
|
1631
1683
|
result_type, = *node.children[4]
|
1632
|
-
|
1684
|
+
rlse node, "result directive expects a symbol argument (got #{result_type}) in node #{node}" \
|
1633
1685
|
unless result_type.is_a? Symbol
|
1634
1686
|
@wgenerator.declare_method(wnode, WType.new(class_path_name), method_name.to_sym, result_type)
|
1635
1687
|
else
|
1636
|
-
|
1688
|
+
rlse node, "result declaration not supported #{wn.scope} scope"
|
1637
1689
|
end
|
1638
1690
|
return
|
1639
1691
|
end
|
@@ -1652,21 +1704,21 @@ module Rlang::Parser
|
|
1652
1704
|
# s(:sym, :ptr),
|
1653
1705
|
# s(:sym, :size))
|
1654
1706
|
def parse_send_attr(node, wnode, keep_eval)
|
1655
|
-
|
1707
|
+
rlse node, "attr directives can only happen in class scope" \
|
1656
1708
|
unless wnode.in_class_scope?
|
1657
1709
|
|
1658
1710
|
# check accessor directive is valid
|
1659
1711
|
attr_access = node.children[1].to_s
|
1660
|
-
|
1712
|
+
rlse node, "Unknown kind of attribute accessor: #{attr_access}" \
|
1661
1713
|
unless ['attr_reader', 'attr_writer', 'attr_accessor'].include? attr_access
|
1662
1714
|
# scan through all attributes
|
1663
1715
|
attr_nodes = node.children[2..-1]
|
1664
1716
|
attr_nodes.each do |an|
|
1665
1717
|
logger.debug "processing attr node #{an}"
|
1666
|
-
|
1718
|
+
rlse node, "attribute name must be a symbol (got #{an})" unless an.type == :sym
|
1667
1719
|
attr_name = an.children.last
|
1668
1720
|
if (attr = wnode.find_attr(attr_name))
|
1669
|
-
|
1721
|
+
rlse node, "attribute #{attr_name} already declared" if attr
|
1670
1722
|
else
|
1671
1723
|
attr = wnode.create_attr(attr_name)
|
1672
1724
|
attr.export!
|
@@ -1692,7 +1744,7 @@ module Rlang::Parser
|
|
1692
1744
|
# s(:sym, :I32)) ))
|
1693
1745
|
#
|
1694
1746
|
def parse_send_attr_type(node, wnode, keep_eval)
|
1695
|
-
|
1747
|
+
rlse node, "attr directives can only happen in class scope" \
|
1696
1748
|
unless wnode.in_class_scope?
|
1697
1749
|
hash_node = node.children.last
|
1698
1750
|
attr_types = parse_type_args(hash_node, :attribute)
|
@@ -1702,7 +1754,7 @@ module Rlang::Parser
|
|
1702
1754
|
# TODO find a way to update both wtype at once
|
1703
1755
|
attr.wtype = WType.new(wtype)
|
1704
1756
|
else
|
1705
|
-
|
1757
|
+
rlse node, "Unknown class attribute #{name} in #{wnode.head}"
|
1706
1758
|
end
|
1707
1759
|
end
|
1708
1760
|
return
|
@@ -1740,17 +1792,17 @@ module Rlang::Parser
|
|
1740
1792
|
# (str "call_indirect(state, cf, opcodes, opcode)"))
|
1741
1793
|
#
|
1742
1794
|
def parse_send_inline(node, wnode, keep_eval)
|
1743
|
-
|
1795
|
+
rlse node, "inline can only happen in a method body or at root" \
|
1744
1796
|
unless wnode.in_method_scope? || wnode.in_root_scope?
|
1745
1797
|
hash_node = node.children.last
|
1746
|
-
|
1798
|
+
rlse node, "inline expects a hash argument (got #{hash_node.type}" \
|
1747
1799
|
unless hash_node.type == :hash
|
1748
1800
|
|
1749
1801
|
# Find the :wat entry in hash
|
1750
1802
|
logger.debug "Hash node: #{hash_node} "
|
1751
1803
|
wat_node = hash_node.children.\
|
1752
1804
|
find {|pair| sym_node, = *pair.children; sym_node.children.last == :wat}
|
1753
|
-
|
1805
|
+
rlse node, "inline has no wat: hash entry" unless wat_node
|
1754
1806
|
logger.debug "inline wat entry: #{wat_node}"
|
1755
1807
|
|
1756
1808
|
# Find the :wtype entry in hash if any
|
@@ -1765,7 +1817,7 @@ module Rlang::Parser
|
|
1765
1817
|
logger.debug "wtype: #{wtype} "
|
1766
1818
|
|
1767
1819
|
# Now extract the WAT code itself
|
1768
|
-
|
1820
|
+
rlse node, "inline has no wat: hash entry" unless wat_node
|
1769
1821
|
wcode_node = wat_node.children.last
|
1770
1822
|
if wcode_node.type == :dstr
|
1771
1823
|
# iterate over str children
|
@@ -1773,7 +1825,7 @@ module Rlang::Parser
|
|
1773
1825
|
elsif wcode_node.type == :str
|
1774
1826
|
wat_code = wcode_node.children.last
|
1775
1827
|
else
|
1776
|
-
|
1828
|
+
rlse node, "inline WAT code must be a string (got #{wcode_node})"
|
1777
1829
|
end
|
1778
1830
|
wn_inline = @wgenerator.inline(wnode, wat_code, wtype)
|
1779
1831
|
# Drop last evaluated result if asked to
|
@@ -1798,7 +1850,7 @@ module Rlang::Parser
|
|
1798
1850
|
const_path = _build_const_path(recv_node)
|
1799
1851
|
# if this is a Constant, not a class
|
1800
1852
|
# then it's actually an instance method call
|
1801
|
-
|
1853
|
+
rlse node, "Unknown constant #{const_path}" unless (c = wnode.find_const(const_path))
|
1802
1854
|
if (c.class? || c.module?)
|
1803
1855
|
return parse_send_class_method_call(node, wnode, keep_eval)
|
1804
1856
|
else
|
@@ -1853,7 +1905,7 @@ module Rlang::Parser
|
|
1853
1905
|
elsif recv_node.type == :const
|
1854
1906
|
class_path = _build_const_path(recv_node)
|
1855
1907
|
else
|
1856
|
-
|
1908
|
+
rlse node, "Can only call method class on self or class objects (got #{recv_node} in node #{node})"
|
1857
1909
|
end
|
1858
1910
|
logger.debug "...#{class_path}::#{method_name}"
|
1859
1911
|
if method_name == :new && (wnode.in_class_scope? || wnode.in_root_scope?)
|
@@ -1872,7 +1924,7 @@ module Rlang::Parser
|
|
1872
1924
|
@wgenerator.drop(wnode) unless (keep_eval || wn_call.wtype.blank?)
|
1873
1925
|
return wn_call
|
1874
1926
|
end
|
1875
|
-
|
1927
|
+
rlse node, "FATAL ERROR!! Unreachable point at end of parse_send_class_method_call (node: #{node})"
|
1876
1928
|
end
|
1877
1929
|
|
1878
1930
|
# Instance Method lookup and native operator
|
@@ -1925,28 +1977,28 @@ module Rlang::Parser
|
|
1925
1977
|
logger.debug "Parsing instance method call #{method_name}, keep_eval: #{keep_eval}..."
|
1926
1978
|
logger.debug "... on receiver #{recv_node}..."
|
1927
1979
|
|
1928
|
-
# parse the receiver node just to
|
1929
|
-
# if nil it means self
|
1980
|
+
# parse the receiver node just to determine its wtype
|
1981
|
+
# if receiver node is nil it means the receiver is self
|
1930
1982
|
wn_phony = @wgenerator.phony(wnode)
|
1931
|
-
|
1932
1983
|
wn_recv = recv_node.nil? ? parse_self(recv_node, wn_phony) : parse_node(recv_node, wn_phony)
|
1933
1984
|
logger.debug "Parsed receiver : #{wn_recv} / wtype: #{wn_recv.wtype}"
|
1934
1985
|
|
1935
|
-
#
|
1986
|
+
# Generate method call code
|
1936
1987
|
wn_op = @wgenerator.send_method(wnode, wn_recv.wtype.class_path, method_name, :instance)
|
1937
1988
|
|
1938
1989
|
# reparent the receiver wnode(s) to operator wnode
|
1939
1990
|
wn_phony.reparent_children_to(wn_op)
|
1940
1991
|
wnode.remove_child(wn_phony)
|
1941
1992
|
|
1942
|
-
# Grab all
|
1993
|
+
# Grab all argument nodes, parse them and add them as child
|
1994
|
+
# to the method call node
|
1943
1995
|
arg_nodes = node.children[2..-1]
|
1944
1996
|
wn_args = arg_nodes.collect do |n|
|
1945
1997
|
logger.debug "...with arg #{n}"
|
1946
1998
|
parse_node(n, wn_op, true)
|
1947
1999
|
end
|
1948
2000
|
|
1949
|
-
# now
|
2001
|
+
# now process operands (e.g. cast them if needed)
|
1950
2002
|
@wgenerator.operands(wn_op, wn_recv, wn_args)
|
1951
2003
|
logger.debug "After operands, call wnode: #{wn_op} wtype: #{wn_op.wtype}, wn_op children types: #{wn_op.children.map(&:wtype)}"
|
1952
2004
|
|
@@ -1961,14 +2013,14 @@ module Rlang::Parser
|
|
1961
2013
|
types = {}
|
1962
2014
|
# Is this a hash Node ?
|
1963
2015
|
unless hash_node.respond_to?(:type) && hash_node.type == :hash
|
1964
|
-
|
2016
|
+
rlse hash_node, "#{entity} expects a hash argument (got #{hash_node}" \
|
1965
2017
|
end
|
1966
2018
|
logger.debug "#{entity} hash node: #{hash_node}"
|
1967
2019
|
hash_node.children.each do |pair_node|
|
1968
2020
|
name_node, type_node = pair_node.children
|
1969
|
-
|
2021
|
+
rlse name_node, "The name of an #{entity} must be a symbol (got #{name_node})" \
|
1970
2022
|
unless name_node.type == :sym
|
1971
|
-
|
2023
|
+
rlse type_node, "The type of an #{entity} must be a symbol (got #{type_node})" \
|
1972
2024
|
unless type_node.type == :sym
|
1973
2025
|
name = name_node.children.last
|
1974
2026
|
type = type_node.children.last
|
@@ -1992,7 +2044,7 @@ module Rlang::Parser
|
|
1992
2044
|
# TODO: not sure this is the right thing to do. Double check
|
1993
2045
|
logger.debug "self in class definition scope. Nothing to do."
|
1994
2046
|
else
|
1995
|
-
|
2047
|
+
rlse node, "Don't know what self means in this context: #{wnode.head}"
|
1996
2048
|
end
|
1997
2049
|
wn
|
1998
2050
|
end
|
@@ -2011,27 +2063,27 @@ module Rlang::Parser
|
|
2011
2063
|
logger.debug "in send: recv_node #{recv_node}, method_name #{method_name}"
|
2012
2064
|
case method_name
|
2013
2065
|
when :to_I64
|
2014
|
-
|
2066
|
+
rlse node, "Data type casting can only apply to int (got #{recv_node}" \
|
2015
2067
|
unless recv_node.type == :int
|
2016
2068
|
value = recv_node.children.last
|
2017
2069
|
DAta.append(label, value, Type::I64)
|
2018
2070
|
when :[]
|
2019
|
-
|
2071
|
+
rlse node, "Initializer can only be a Data address (got #{node})" \
|
2020
2072
|
unless recv_node.children.last == :DAta
|
2021
|
-
|
2073
|
+
rlse node, "Initializer expects a symbol (got #{arg_node})" \
|
2022
2074
|
unless arg_node.type == :sym
|
2023
2075
|
DAta.append(label, DAta[arg_node.children.last])
|
2024
2076
|
else
|
2025
|
-
|
2077
|
+
rlse node, "Unknow data initializer #{node}"
|
2026
2078
|
end
|
2027
2079
|
else
|
2028
|
-
|
2080
|
+
rlse node, "Unknow data initializer #{node}"
|
2029
2081
|
end
|
2030
2082
|
end
|
2031
2083
|
|
2032
2084
|
def parse_return(node, wnode, keep_eval)
|
2033
2085
|
ret_count = node.children.count
|
2034
|
-
|
2086
|
+
rlse node, "only one or no value can be returned (got #{ret_count})" if ret_count > 1
|
2035
2087
|
exp_node = node.children.first
|
2036
2088
|
wn_ret = @wgenerator.return(wnode)
|
2037
2089
|
if exp_node
|
@@ -2141,7 +2193,7 @@ module Rlang::Parser
|
|
2141
2193
|
parse_node(else_node, wn_else, keep_eval)
|
2142
2194
|
wn_else.wtype = wn_else.children.last.wtype
|
2143
2195
|
if wn_then.wtype != wn_else.wtype
|
2144
|
-
|
2196
|
+
rlse node, "then and else clauses must return same wtype (got #{wn_then.wtype} and #{wn_else.wtype}"
|
2145
2197
|
end
|
2146
2198
|
else
|
2147
2199
|
# if the else clause doesn't exist in Ruby we still
|
@@ -2243,7 +2295,7 @@ module Rlang::Parser
|
|
2243
2295
|
logger.debug "Building constant path..."
|
2244
2296
|
const_path = []; n = node
|
2245
2297
|
while n
|
2246
|
-
|
2298
|
+
rlse node, "expecting a const node (got #{n})" unless n.type == :const
|
2247
2299
|
logger.debug "adding #{n.children.last} to constant path"
|
2248
2300
|
const_path.unshift(n.children.last)
|
2249
2301
|
n = n.children.first
|