Skip to content

Commit dd42626

Browse files
committed
[truffle] Implement nqp::<l?stat l?stat_time>
1 parent 9e59b16 commit dd42626

File tree

6 files changed

+328
-0
lines changed

6 files changed

+328
-0
lines changed

src/vm/jvm/Truffle.nqp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ class QAST::OperationsTruffle {
236236
add_simple_op('replace', $STR, [$STR, $INT, $INT, $STR]);
237237
add_simple_op('codes', $INT, [$STR]);
238238

239+
add_simple_op('stat', $INT, [$STR, $INT]);
240+
add_simple_op('lstat', $INT, [$STR, $INT]);
241+
add_simple_op('stat_time', $NUM, [$STR, $INT]);
242+
add_simple_op('lstat_time', $NUM, [$STR, $INT]);
243+
239244
for <postinc postdec> -> $op {
240245
add_op($op, sub ($comp, $node, :$want) {
241246
my $old_value := $comp.as_truffle($node[0], :want($INT));
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.perl6.nqp.truffle.nodes.expression;
2+
import com.oracle.truffle.api.frame.VirtualFrame;
3+
import com.oracle.truffle.api.nodes.NodeInfo;
4+
import org.perl6.nqp.truffle.nodes.NQPNode;
5+
import org.perl6.nqp.truffle.nodes.NQPIntNode;
6+
import org.perl6.nqp.truffle.runtime.FileOps;
7+
import org.perl6.nqp.dsl.Deserializer;
8+
import java.nio.file.LinkOption;
9+
10+
@NodeInfo(shortName = "lstat")
11+
public final class NQPLstatNode extends NQPIntNode {
12+
@Child private NQPNode leftNode;
13+
@Child private NQPNode rightNode;
14+
15+
@Deserializer
16+
public NQPLstatNode(NQPNode leftNode, NQPNode rightNode) {
17+
this.leftNode = leftNode;
18+
this.rightNode = rightNode;
19+
}
20+
21+
@Override
22+
public long executeInt(VirtualFrame frame) {
23+
return FileOps.stat_internal(leftNode.executeStr(frame), rightNode.executeInt(frame), LinkOption.NOFOLLOW_LINKS);
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.perl6.nqp.truffle.nodes.expression;
2+
import com.oracle.truffle.api.frame.VirtualFrame;
3+
import com.oracle.truffle.api.nodes.NodeInfo;
4+
import org.perl6.nqp.truffle.nodes.NQPNode;
5+
import org.perl6.nqp.truffle.nodes.NQPIntNode;
6+
import org.perl6.nqp.truffle.runtime.FileOps;
7+
import org.perl6.nqp.dsl.Deserializer;
8+
import java.nio.file.LinkOption;
9+
10+
@NodeInfo(shortName = "lstat_time")
11+
public final class NQPLstat_timeNode extends NQPIntNode {
12+
@Child private NQPNode leftNode;
13+
@Child private NQPNode rightNode;
14+
15+
@Deserializer
16+
public NQPLstat_timeNode(NQPNode leftNode, NQPNode rightNode) {
17+
this.leftNode = leftNode;
18+
this.rightNode = rightNode;
19+
}
20+
21+
@Override
22+
public double executeNum(VirtualFrame frame) {
23+
return FileOps.stat_time_internal(leftNode.executeStr(frame), rightNode.executeInt(frame), LinkOption.NOFOLLOW_LINKS);
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.perl6.nqp.truffle.nodes.expression;
2+
import com.oracle.truffle.api.frame.VirtualFrame;
3+
import com.oracle.truffle.api.nodes.NodeInfo;
4+
import org.perl6.nqp.truffle.nodes.NQPNode;
5+
import org.perl6.nqp.truffle.nodes.NQPIntNode;
6+
import org.perl6.nqp.truffle.runtime.FileOps;
7+
import org.perl6.nqp.dsl.Deserializer;
8+
9+
@NodeInfo(shortName = "stat")
10+
public final class NQPStatNode extends NQPIntNode {
11+
@Child private NQPNode leftNode;
12+
@Child private NQPNode rightNode;
13+
14+
@Deserializer
15+
public NQPStatNode(NQPNode leftNode, NQPNode rightNode) {
16+
this.leftNode = leftNode;
17+
this.rightNode = rightNode;
18+
}
19+
20+
@Override
21+
public long executeInt(VirtualFrame frame) {
22+
return FileOps.stat_internal(leftNode.executeStr(frame), rightNode.executeInt(frame));
23+
}
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.perl6.nqp.truffle.nodes.expression;
2+
import com.oracle.truffle.api.frame.VirtualFrame;
3+
import com.oracle.truffle.api.nodes.NodeInfo;
4+
import org.perl6.nqp.truffle.nodes.NQPNode;
5+
import org.perl6.nqp.truffle.nodes.NQPIntNode;
6+
import org.perl6.nqp.truffle.runtime.FileOps;
7+
import org.perl6.nqp.dsl.Deserializer;
8+
9+
@NodeInfo(shortName = "stat_time")
10+
public final class NQPStat_timeNode extends NQPIntNode {
11+
@Child private NQPNode leftNode;
12+
@Child private NQPNode rightNode;
13+
14+
@Deserializer
15+
public NQPStat_timeNode(NQPNode leftNode, NQPNode rightNode) {
16+
this.leftNode = leftNode;
17+
this.rightNode = rightNode;
18+
}
19+
20+
@Override
21+
public double executeNum(VirtualFrame frame) {
22+
return FileOps.stat_time_internal(leftNode.executeStr(frame), rightNode.executeInt(frame));
23+
}
24+
}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package org.perl6.nqp.truffle.runtime;
2+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
3+
import java.io.File;
4+
import java.nio.file.Files;
5+
import java.nio.file.LinkOption;
6+
import java.nio.file.NotLinkException;
7+
import java.nio.file.NoSuchFileException;
8+
import java.nio.file.Paths;
9+
import java.nio.file.attribute.BasicFileAttributes;
10+
import java.nio.file.attribute.FileTime;
11+
import java.util.concurrent.TimeUnit;
12+
13+
public class FileOps {
14+
15+
public static final int STAT_EXISTS = 0;
16+
public static final int STAT_FILESIZE = 1;
17+
public static final int STAT_ISDIR = 2;
18+
public static final int STAT_ISREG = 3;
19+
public static final int STAT_ISDEV = 4;
20+
public static final int STAT_CREATETIME = 5;
21+
public static final int STAT_ACCESSTIME = 6;
22+
public static final int STAT_MODIFYTIME = 7;
23+
public static final int STAT_CHANGETIME = 8;
24+
public static final int STAT_BACKUPTIME = 9;
25+
public static final int STAT_UID = 10;
26+
public static final int STAT_GID = 11;
27+
public static final int STAT_ISLNK = 12;
28+
public static final int STAT_PLATFORM_DEV = -1;
29+
public static final int STAT_PLATFORM_INODE = -2;
30+
public static final int STAT_PLATFORM_MODE = -3;
31+
public static final int STAT_PLATFORM_NLINKS = -4;
32+
public static final int STAT_PLATFORM_DEVTYPE = -5;
33+
public static final int STAT_PLATFORM_BLOCKSIZE = -6;
34+
public static final int STAT_PLATFORM_BLOCKS = -7;
35+
36+
@TruffleBoundary
37+
public static long stat_internal(String filename, long status, LinkOption ... linkOption) {
38+
long rval = -1;
39+
40+
switch ((int) status) {
41+
case STAT_EXISTS:
42+
rval = Files.exists(Paths.get(filename), linkOption) ? 1 : 0;
43+
break;
44+
45+
case STAT_FILESIZE:
46+
try {
47+
rval = Files.readAttributes(Paths.get(filename), BasicFileAttributes.class, linkOption).size();
48+
} catch (Exception e) {
49+
rval = -1;
50+
}
51+
break;
52+
53+
case STAT_ISDIR:
54+
try {
55+
rval = (Boolean) Files.getAttribute(Paths.get(filename), "basic:isDirectory", linkOption) ? 1 : 0;
56+
} catch(NoSuchFileException e) {
57+
rval = 0;
58+
} catch (Exception e) {
59+
rval = -1;
60+
}
61+
break;
62+
63+
case STAT_ISREG:
64+
try {
65+
rval = (Boolean) Files.getAttribute(Paths.get(filename), "basic:isRegularFile", linkOption) ? 1 : 0;
66+
} catch(NoSuchFileException e) {
67+
rval = 0;
68+
} catch (Exception e) {
69+
rval = -1;
70+
}
71+
break;
72+
73+
case STAT_ISDEV:
74+
try {
75+
rval = (Boolean) Files.getAttribute(Paths.get(filename), "basic:isOther", linkOption) ? 1 : 0;
76+
} catch(NoSuchFileException e) {
77+
rval = 0;
78+
} catch (Exception e) {
79+
rval = -1;
80+
}
81+
break;
82+
83+
case STAT_CREATETIME:
84+
try {
85+
rval = ((Number) Files.getAttribute(Paths.get(filename), "basic:creationTime", linkOption)).longValue();
86+
} catch (Exception e) {
87+
rval = -1;
88+
}
89+
break;
90+
91+
case STAT_ACCESSTIME:
92+
try {
93+
rval = ((FileTime) Files.getAttribute(Paths.get(filename), "basic:lastAccessTime", linkOption)).to(TimeUnit.SECONDS);
94+
} catch (Exception e) {
95+
rval = -1;
96+
}
97+
break;
98+
99+
case STAT_MODIFYTIME:
100+
try {
101+
rval = ((FileTime) Files.getAttribute(Paths.get(filename), "basic:lastModifiedTime", linkOption)).to(TimeUnit.SECONDS);
102+
} catch (Exception e) {
103+
rval = -1;
104+
}
105+
break;
106+
107+
case STAT_CHANGETIME:
108+
try {
109+
rval = ((FileTime) Files.getAttribute(Paths.get(filename), "unix:ctime", linkOption)).to(TimeUnit.SECONDS);
110+
} catch (Exception e) {
111+
rval = -1;
112+
}
113+
break;
114+
115+
case STAT_BACKUPTIME:
116+
rval = -1;
117+
break;
118+
119+
case STAT_UID:
120+
try {
121+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:uid", linkOption)).longValue();
122+
} catch (Exception e) {
123+
rval = -1;
124+
}
125+
break;
126+
127+
case STAT_GID:
128+
try {
129+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:gid", linkOption)).longValue();
130+
} catch (Exception e) {
131+
rval = -1;
132+
}
133+
break;
134+
135+
case STAT_ISLNK:
136+
try {
137+
rval = (Boolean) Files.getAttribute(Paths.get(filename), "basic:isSymbolicLink", LinkOption.NOFOLLOW_LINKS) ? 1 : 0;
138+
} catch(NoSuchFileException e) {
139+
rval = 0;
140+
} catch (Exception e) {
141+
rval = -1;
142+
}
143+
break;
144+
145+
case STAT_PLATFORM_DEV:
146+
try {
147+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:dev", linkOption)).longValue();
148+
} catch (Exception e) {
149+
rval = -1;
150+
}
151+
break;
152+
153+
case STAT_PLATFORM_INODE:
154+
try {
155+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:ino", linkOption)).longValue();
156+
} catch (Exception e) {
157+
rval = -1;
158+
}
159+
break;
160+
161+
case STAT_PLATFORM_MODE:
162+
try {
163+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:mode", linkOption)).longValue();
164+
} catch (Exception e) {
165+
rval = -1;
166+
}
167+
break;
168+
169+
case STAT_PLATFORM_NLINKS:
170+
try {
171+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:nlink", linkOption)).longValue();
172+
} catch (Exception e) {
173+
rval = -1;
174+
}
175+
break;
176+
177+
case STAT_PLATFORM_DEVTYPE:
178+
try {
179+
rval = ((Number) Files.getAttribute(Paths.get(filename), "unix:rdev", linkOption)).longValue();
180+
} catch (Exception e) {
181+
rval = -1;
182+
}
183+
break;
184+
185+
case STAT_PLATFORM_BLOCKSIZE:
186+
throw new UnsupportedOperationException("STAT_PLATFORM_BLOCKSIZE not supported");
187+
188+
case STAT_PLATFORM_BLOCKS:
189+
throw new UnsupportedOperationException("STAT_PLATFORM_BLOCKS not supported");
190+
191+
default:
192+
break;
193+
}
194+
195+
return rval;
196+
}
197+
198+
@TruffleBoundary
199+
public static double stat_time_internal(String filename, long status, LinkOption... linkOption) {
200+
String attrName;
201+
switch ((int) status) {
202+
case STAT_CREATETIME:
203+
attrName = "basic:creationTime";
204+
break;
205+
case STAT_ACCESSTIME:
206+
attrName = "basic:lastAccessTime";
207+
break;
208+
case STAT_MODIFYTIME:
209+
attrName = "basic:lastModifiedTime";
210+
break;
211+
case STAT_CHANGETIME:
212+
attrName = "unix:ctime";
213+
break;
214+
default:
215+
return -1;
216+
}
217+
218+
try {
219+
FileTime ft = ((FileTime) Files.getAttribute(Paths.get(filename), attrName, linkOption));
220+
return ft.to(TimeUnit.NANOSECONDS) / 1000000000;
221+
} catch (Exception e) {
222+
return -1;
223+
}
224+
}
225+
}

0 commit comments

Comments
 (0)