forked from gracelang/minigrace
-
Notifications
You must be signed in to change notification settings - Fork 3
/
intrinsic.grace
173 lines (161 loc) · 5.89 KB
/
intrinsic.grace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
dialect "none"
// The intrinsic module. This is the home for language elements that cannot
// be defined in Grace itself because they are beyond the descriptive power
// of the language.
once method Exception { native "js" code ‹return ExceptionObject;› }
def UnimplementedMethod = Exception.refine "UnimplementedMethod"
def NoneType = object {
method name { "None" }
method matches(obj) { false }
method | (other) { other }
method & (other) { self }
method prefix ¬ { interface { } }
method +(other) { other }
method -(other) {
UnimplementedMethod.raise "can't subtract methods from type {name}"
}
method asString { "type {name}" }
method methodNames {
UnimplementedMethod.raise
"can't get the methods of type {name} because they form an infinite set"
}
method ==(other) { self.isMe(other) }
method hash { myIdentityHash }
method isNone { true }
method isType { true }
}
trait annotations {
// these _can_ be declared in Grace, but we don't want to repeat the
// definitions in many files
method annotation is annotation
method required is annotation
method abstract is annotation
method confidential is annotation
method public is annotation
method readable is annotation
method writable is annotation
method override is annotation
}
trait constants {
method Exception { outer.Exception }
method UnimplementedMethod { outer.UnimplementedMethod }
method ProgrammingError { native "js" code ‹
return ProgrammingErrorObject; ›
}
method EnvironmentException { native "js" code ‹
return EnvironmentExceptionObject; ›
}
method ResourceException { native "js" code ‹
return ResourceExceptionObject; ›
}
method RuntimeError { native "js" code ‹
return RuntimeErrorObject; ›
}
method TypeError { native "js" code ‹
return TypeErrorObject; ›
}
method NoSuchMethod { native "js" code ‹
return NoSuchMethodErrorObject; ›
}
method BoundsError { native "js" code ‹
return BoundsErrorObject; ›
}
method IteratorExhausted { native "js" code ‹
return IteratorExhaustedObject; ›
}
method NoSuchObject { native "js" code ‹
return NoSuchObjectErrorObject; ›
}
once method DialectError {
Exception.refine "DialectError"
}
once method infinity { native "js" code ‹
return new GraceNum(Infinity); ›
}
method done { native "js" code ‹
return GraceDone;›
}
once class primitiveArray {
method new(size) {
native "js" code ‹return new GracePrimitiveArray(var_size._value);›
}
}
}
trait controlStructures {
method while (cond) do (block) {
native "js" code ‹
const c = var_cond;
const b = var_block;
if (c.className === "boolean" || c.className === "number")
throw new GraceExceptionPacket(TypeErrorObject,
new GraceString("expected Block for first argument of " +
"while(_)do(_), got " + c.className + "."));
if ((typeof minigrace != "undefined") && minigrace.breakLoops) {
var count = 0;
var runningTime = 0;
var runningCount = 0;
var startTime = new Date();
var diff;
while (Grace_isTrue(callmethod(c, "apply", [0]))) {
count++;
if (count % 100000 === 0 && ((diff=new Date()-startTime) > 5000)) {
var totTime = runningTime + diff;
var totIterations = runningCount + count;
if (! confirm("A while loop is taking a long time to run. " +
"Do you want to continue? " +
totIterations + " iterations of the loop have taken " +
totTime + "ms so far." +
"\n\nChoose Cancel to stop the program, or OK to " +
"let it continue."))
throw new GraceExceptionPacket(ResourceExceptionObject,
new GraceString("user abort of long-running loop."));
else {
runningCount += count;
runningTime += diff;
count = 0;
startTime = new Date();
}
}
callmethod(b, "apply", [0]);
}
} else {
while (Grace_isTrue(callmethod(c, "apply", [0]))) {
callmethod(b, "apply", [0]);
}
}
return GraceDone;›
}
}
method inBrowser {
native "js" code ‹return (typeof global === "undefined") ? GraceTrue : GraceFalse;›
}
method engine {
native "js" code ‹return new GraceString("js");› // only when generating JS
constants.ProgrammingError.raise "the method `engine` must be augmented to support this execution engine"
}
method become(a, b) {
// not clear what this is actualy intended to do ... it's used in statictypes dialect
// it won't exchange the prototypes of the two objects, so they may not work.
native "js" code ‹
for (let k in var_a) {
const temp = var_a[k];
var_a[k] = var_b[k];
var_b[k] = temp;
}
GraceDone;
›
}
method hashCombine(a, b) {
native "c" code ‹
int a = (int)(args[0]->data);
int b = (int)(args[1]->data);
int aHash = a * 1664525;
int bHash = (b * 1664525 - 0xA21FE89) * 3;
return alloc_Float64((aHash * 2) ^ bHash);›
native "js" code ‹
var a = var_a._value;
var b = var_b._value;
var aHash = a * 1664525;
var bHash = (b * 1664525 - 0xA21FE89) * 3;
result = new GraceNum((aHash * 2) ^ bHash);›
}