rlang 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|