Skip to content

Commit 4e14314

Browse files
feat: Add support for function arguments. (#3)
This includes support for array indexing and hash lookups.
1 parent cfaa9b6 commit 4e14314

File tree

4 files changed

+111
-27
lines changed

4 files changed

+111
-27
lines changed

cfg/Instructions.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,11 @@ Send::Send(LocalRef recv, core::LocOffsets receiverLoc, core::NameRef fun, core:
130130
args.size());
131131

132132
this->args.resize(args.size());
133+
ENFORCE(this->args.size() == this->argLocs.size(), "Expected number of args and argLocs to match");
133134
int i = 0;
134135
for (const auto &e : args) {
135136
this->args[i].variable = e;
137+
this->args[i].loc = this->argLocs[i]; // NOTE(varun): loc copying
136138
i++;
137139
}
138140
categoryCounterInc("cfg", "send");

scip_indexer/SCIPIndexer.cc

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -518,29 +518,37 @@ class CFGTraversal final {
518518
case cfg::Tag::Send: {
519519
// emit occurrence for function
520520
auto send = cfg::cast_instruction<cfg::Send>(binding.value);
521-
if (!send->fun.exists()) {
522-
// TODO(varun): when does this happen?
523-
continue;
524-
}
521+
525522
// Emit reference for the receiver, if present.
526523
if (send->recv.loc.exists() && !send->recv.loc.empty()) {
527524
this->emitLocalOccurrence(cfg, bb, send->recv.occurrence(), ValueCategory::RValue);
528525
}
529526

530527
// Emit reference for the method being called
531-
if (!isTemporary(gs, core::LocalVariable(send->fun, 1))) {
528+
if (send->fun.exists() && !isTemporary(gs, core::LocalVariable(send->fun, 1))) {
532529
// HACK(varun): We should probably add a helper function to check
533530
// for names corresponding to temporaries? Making up a fake local
534531
// variable seems a little gross.
535532
auto funSym = lookupRecursive(gs, method, send->fun);
536-
if (!funSym.exists()) {
537-
print_err("# lookup for fun symbol {} failed\n", send->fun.shortName(gs));
538-
continue;
533+
if (funSym.exists()) {
534+
ENFORCE(send->funLoc.exists() && !send->funLoc.empty());
535+
auto status =
536+
this->scipState.saveReference(gs, this->ctx.file, funSym, send->funLoc, 0);
537+
ENFORCE(status.ok());
539538
}
540-
ENFORCE(send->funLoc.exists());
541-
ENFORCE(!send->funLoc.empty());
542-
auto status = this->scipState.saveReference(gs, this->ctx.file, funSym, send->funLoc, 0);
543-
ENFORCE_NO_TIMER(status.ok());
539+
print_err("# lookup for fun symbol {} failed\n", send->fun.shortName(gs));
540+
}
541+
542+
// Emit references for arguments
543+
for (auto &arg : send->args) {
544+
// NOTE: For constructs like a += b, the instruction sequence ends up being:
545+
// $tmp = $b
546+
// $a = $tmp.+($b)
547+
// The location for $tmp will point to $a in the source. However, the second one is a read,
548+
// and the first one is a write. Instead of emitting two occurrences, it'd be nice to emit
549+
// a combined read-write occurrence. However, that would require complicating the code a
550+
// bit, so let's leave it as-is for now.
551+
this->emitLocalOccurrence(cfg, bb, arg.occurrence(), ValueCategory::RValue);
544552
}
545553

546554
break;

test/scip/testdata/syntax.rb

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# typed: true
22

3-
a = [57, 33]
4-
i = 0
5-
a[i] # a.[](i)
6-
a << 970 # a.push(970)
7-
a[2..-1]
3+
_ = 0 # stub for global <static-init>
84

95
def globalFn1()
106
x = 10
@@ -14,3 +10,27 @@ def globalFn1()
1410
def globalFn2()
1511
x = globalFn1()
1612
end
13+
14+
def args(x, y)
15+
z = x + y
16+
if x == 2
17+
z += y
18+
else
19+
z += x
20+
end
21+
z
22+
end
23+
24+
def arrays(a, i)
25+
a[0] = 0
26+
a[1] = a[2]
27+
a[i] = a[i + 1]
28+
b = a[2..-1]
29+
a << a[-1]
30+
end
31+
32+
def hashes(h, k)
33+
h["hello"] = "world"
34+
old = h["world"]
35+
h[k] = h[old]
36+
end

test/scip/testdata/syntax.rb.snapshot

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
# typed: true
22

3-
a = [57, 33]
3+
_ = 0 # stub for global <static-init>
44
#^ definition local 1~#119448696
5-
#^^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO <static-init>().
6-
i = 0
7-
#^ definition local 2~#119448696
8-
a[i] # a.[](i)
9-
#^ reference local 1~#119448696
10-
a << 970 # a.push(970)
11-
#^ reference local 1~#119448696
12-
a[2..-1]
13-
#^ reference local 1~#119448696
5+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO <static-init>().
146

157
def globalFn1()
168
#^^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO globalFn1().
@@ -27,3 +19,65 @@
2719
# ^^^^^^^^^^^^^^^ reference local 1~#3796204016
2820
# ^^^^^^^^^ reference scip-ruby gem TODO TODO globalFn1().
2921
end
22+
23+
def args(x, y)
24+
#^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO args().
25+
# ^ definition local 1~#2634721084
26+
# ^ definition local 2~#2634721084
27+
z = x + y
28+
# ^ definition local 3~#2634721084
29+
# ^ reference local 1~#2634721084
30+
# ^ reference local 2~#2634721084
31+
if x == 2
32+
# ^ reference local 1~#2634721084
33+
z += y
34+
# ^ reference local 3~#2634721084
35+
# ^ reference local 3~#2634721084
36+
# ^ reference local 2~#2634721084
37+
else
38+
z += x
39+
# ^ reference local 3~#2634721084
40+
# ^ reference local 3~#2634721084
41+
# ^ reference local 1~#2634721084
42+
end
43+
z
44+
# ^ reference local 3~#2634721084
45+
end
46+
47+
def arrays(a, i)
48+
#^^^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO arrays().
49+
# ^ definition local 1~#513334479
50+
# ^ definition local 2~#513334479
51+
a[0] = 0
52+
# ^ reference local 1~#513334479
53+
a[1] = a[2]
54+
# ^ reference local 1~#513334479
55+
# ^ reference local 1~#513334479
56+
a[i] = a[i + 1]
57+
# ^ reference local 1~#513334479
58+
# ^ reference local 2~#513334479
59+
# ^ reference local 1~#513334479
60+
# ^ reference local 2~#513334479
61+
b = a[2..-1]
62+
# ^ definition local 3~#513334479
63+
# ^ reference local 1~#513334479
64+
a << a[-1]
65+
# ^ reference local 1~#513334479
66+
# ^ reference local 1~#513334479
67+
end
68+
69+
def hashes(h, k)
70+
#^^^^^^^^^^^^^^^^ definition scip-ruby gem TODO TODO hashes().
71+
# ^ definition local 1~#1685166589
72+
# ^ definition local 2~#1685166589
73+
h["hello"] = "world"
74+
# ^ reference local 1~#1685166589
75+
old = h["world"]
76+
# ^^^ definition local 3~#1685166589
77+
# ^ reference local 1~#1685166589
78+
h[k] = h[old]
79+
# ^ reference local 1~#1685166589
80+
# ^ reference local 2~#1685166589
81+
# ^ reference local 1~#1685166589
82+
# ^^^ reference local 3~#1685166589
83+
end

0 commit comments

Comments
 (0)