Skip to content

Commit 6b372b0

Browse files
committed
Updated exception handling syntax to be more like Python.
We now use try/except, and raise exceptions which must include an enum value, and optionally a message. See design_decisions.md for more info on these changes. In the C Rune compiler, it is implemented with setjmp/longjmp. and the stack is not unwound.
1 parent 378f631 commit 6b372b0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1378
-795
lines changed

bind/bind.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,11 @@ void deQueueStatement(deSignature signature, deStatement statement, bool instant
286286
// Bind return statements even if they have no expression.
287287
binding = deBindingCreate(signature, statement, instantiating);
288288
if (expression != deExpressionNull) {
289-
deQueueExpression(binding, expression, instantiating, false);
289+
if (deStatementGetType(statement) == DE_STATEMENT_TYPESWITCH) {
290+
deQueueExpression(binding, expression, false, false);
291+
} else {
292+
deQueueExpression(binding, expression, instantiating, false);
293+
}
290294
}
291295
deBlock subBlock = deStatementGetSubBlock(statement);
292296
if (deStatementGetType(statement) == DE_STATEMENT_TYPESWITCH) {

bind/bindexpr.c

+17-5
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ static deFunction findMatchingOperatorOverload(deBlock scopeBlock, deExpression
233233
deDatatype selfType = deDatatypeArrayGetiDatatype(paramTypes, 0);
234234
deBlock block;
235235
utSym sym = deGetOperatorSym(opType, numParams == 1);
236-
if (deDatatypeGetType(selfType) == DE_TYPE_CLASS) {
236+
if (!deDatatypeNullable(selfType) && deDatatypeGetType(selfType) == DE_TYPE_CLASS) {
237237
block = deClassGetSubBlock(deDatatypeGetClass(selfType));
238238
deIdent ident = findIdentInBlock(block, sym);
239239
if (ident != deIdentNull) {
@@ -242,7 +242,7 @@ static deFunction findMatchingOperatorOverload(deBlock scopeBlock, deExpression
242242
}
243243
if (numParams == 2) {
244244
selfType = deDatatypeArrayGetiDatatype(paramTypes, 1);
245-
if (deDatatypeGetType(selfType) == DE_TYPE_CLASS) {
245+
if (!deDatatypeNullable(selfType) && deDatatypeGetType(selfType) == DE_TYPE_CLASS) {
246246
block = deClassGetSubBlock(deDatatypeGetClass(selfType));
247247
deIdent ident = deBlockFindIdent(block, sym);
248248
if (ident != deIdentNull) {
@@ -1950,13 +1950,24 @@ static void postProcessBoundStatement(deBlock scopeBlock, deBinding binding) {
19501950
updateSignatureReturnType(deBindingGetSignature(binding), datatype);
19511951
} else if (type == DE_STATEMENT_TYPESWITCH) {
19521952
selectMatchingCase(scopeBlock, binding);
1953-
} else if (type == DE_STATEMENT_PRINT || type == DE_STATEMENT_THROW || type == DE_STATEMENT_PANIC) {
1953+
} else if (type == DE_STATEMENT_PRINT || type == DE_STATEMENT_RAISE) {
19541954
dePostProcessPrintStatement(statement);
1955+
if (type == DE_STATEMENT_RAISE) {
1956+
deExpression expression = deStatementGetExpression(statement);
1957+
deExpression enumExpr = deExpressionGetFirstExpression(expression);
1958+
if (enumExpr == deExpressionNull) {
1959+
deExprError(expression, "Raise statement requires an enum value first");
1960+
}
1961+
deDatatype datatype = deExpressionGetDatatype(enumExpr);
1962+
if (datatype == deDatatypeNull || deDatatypeGetType(datatype) != DE_TYPE_ENUM) {
1963+
deExprError(expression, "Raise statement requires an enum value first");
1964+
}
1965+
}
19551966
} else if (type == DE_STATEMENT_IF) {
19561967
deExpression expression = deStatementGetExpression(statement);
19571968
deDatatype datatype = deExpressionGetDatatype(expression);
19581969
if (datatype == deDatatypeNull || deDatatypeGetType(datatype) != DE_TYPE_BOOL) {
1959-
deExprError(expression, "If statement requires a boolean condition");
1970+
deExprError(expression, "If statement requires a Boolean condition");
19601971
}
19611972
}
19621973
}
@@ -2021,7 +2032,8 @@ void deBindStatement(deBinding binding) {
20212032
deExpression typeExpr = deFunctionGetTypeExpression(function);
20222033
deDatatype datatype = deExpressionGetDatatype(typeExpr);
20232034
deSignature signature = deBindingGetSignature(binding);
2024-
if (deDatatypeConcrete(datatype) && signature != deSignatureNull) {
2035+
if (datatype != deDatatypeNull && deDatatypeConcrete(datatype) &&
2036+
signature != deSignatureNull) {
20252037
updateSignatureReturnType(deBindingGetSignature(binding), datatype);
20262038
}
20272039
if (deFunctionExtern(function)) {

bind/create_vars.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ static void createVariableIfMissing(deBlock scopeBlock, deExpression expr) {
2222
return;
2323
}
2424
deStatement statement = deFindExpressionStatement(expr);
25-
deVariableCreate(scopeBlock, DE_VAR_LOCAL, false, name, deExpressionNull,
25+
deVariable var = deVariableCreate(scopeBlock, DE_VAR_LOCAL, false, name, deExpressionNull,
2626
deStatementGenerated(statement), deExpressionGetLine(expr));
27+
if (deRootGetBlock(deTheRoot) == scopeBlock) {
28+
deVariableSetInstantiated(var, true);
29+
}
2730
}
2831

2932
// Create variables when we find assignment expressions that assign to an identifier.

bootstrap/database/bigint.rn

+121-19
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
5656
self.isSigned = false
5757
self.isSecret = false
5858
typeswitch value {
59-
Int | Uint {
59+
Int | Uint => {
6060
if widthof(value) > kMaxBigintWidth {
61-
throw "Integer width too large. Pass in BigintArray instead."
61+
panic "Integer width too large. Pass in BigintArray instead."
6262
}
6363
if width != 0 {
6464
self.width = width
@@ -76,9 +76,9 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
7676
self.bigint = runtime.integerToBigint(!<u64>value, self.width,
7777
self.isSigned, self.isSecret)
7878
}
79-
runtime.BigintArray {
79+
runtime.BigintArray => {
8080
if width != 0 {
81-
throw "Can't change bigint width in Bigint constructor. Use cast instead."
81+
panic "Can't change bigint width in Bigint constructor. Use cast instead."
8282
}
8383
self.isSigned = runtime.bigintSigned(value)
8484
self.width = runtime.bigintWidth(value)
@@ -103,119 +103,157 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
103103
return text
104104
}
105105

106+
// Return a string representation of the number Little-Endian.
107+
func toStringLE(self) {
108+
s = ""
109+
runtime.bigintEncodeLittleEndian(s, self.bigint)
110+
return s
111+
}
112+
113+
// Convert a string Little-Endian representation to a Bigint.
114+
func fromStringLE(s: string, width: u32, isSigned: bool = false, isSecret: bool = false) {
115+
bigint = arrayof(u32)
116+
runtime.bigintDecodeLittleEndian(bigint, s, width, isSigned, isSecret)
117+
return Bigint(bigint)
118+
}
119+
120+
// Return a string representation of the number Big-Endian.
121+
func toStringBE(self) {
122+
s = ""
123+
runtime.bigintEncodeBigEndian(s, self.bigint)
124+
return s
125+
}
126+
127+
// Convert a string Big-Endian representation to a Bigint.
128+
func fromStringBE(s: string, width: u32, isSigned: bool = false, isSecret: bool = false) {
129+
bigint = arrayof(u32)
130+
runtime.bigintDecodeBigEndian(bigint, s, width, isSigned, isSecret)
131+
return Bigint(bigint)
132+
}
133+
106134
// Cast the bigint to a different width, sign, or even secret status.
107-
export func cast(self, newWidth: u32, isSigned: bool, isSecret: bool, truncate: bool) {
135+
func cast(self, newWidth: u32, isSigned: bool, isSecret: bool, truncate: bool = false) -> Bigint {
108136
return Bigint(runtime.bigintCast(self.bigint, newWidth, isSigned, isSecret, truncate))
109137
}
110138

139+
// Resize the bigint to a different width.
140+
func resize(self, newWidth: u32, truncate: bool = false) -> Bigint {
141+
return self.cast(newWidth, self.isSigned, self.isSecret, truncate)
142+
}
143+
144+
// Set to signed or unsinged.
145+
func toSigned(self, isSigned: bool = true, truncate: bool = false) -> Bigint {
146+
return self.cast(self.width, isSigned, self.isSecret, truncate)
147+
}
148+
111149
// Overload the + operator.
112150
operator + (a: Bigint, b: Bigint) -> Bigint {
113151
if a.width != b.width || a.isSigned != b.isSigned {
114-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
152+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
115153
}
116154
return Bigint(runtime.bigintAdd(a.bigint, b.bigint))
117155
}
118156

119157
// Overload the !+ operator.
120158
operator !+ (a: Bigint, b: Bigint) -> Bigint {
121159
if a.width != b.width || a.isSigned != b.isSigned {
122-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
160+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
123161
}
124162
return Bigint(runtime.bigintAddTrunc(a.bigint, b.bigint))
125163
}
126164

127165
// Overload the - operator.
128166
operator - (a: Bigint, b: Bigint) -> Bigint {
129167
if a.width != b.width || a.isSigned != b.isSigned {
130-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
168+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
131169
}
132170
return Bigint(runtime.bigintSub(a.bigint, b.bigint))
133171
}
134172

135173
// Overload the !- operator.
136174
operator !- (a: Bigint, b: Bigint) -> Bigint {
137175
if a.width != b.width || a.isSigned != b.isSigned {
138-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
176+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
139177
}
140178
return Bigint(runtime.bigintSubTrunc(a.bigint, b.bigint))
141179
}
142180

143181
// Overload the * operator.
144182
operator * (a: Bigint, b: Bigint) -> Bigint {
145183
if a.width != b.width || a.isSigned != b.isSigned {
146-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
184+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
147185
}
148186
return Bigint(runtime.bigintMul(a.bigint, b.bigint))
149187
}
150188

151189
// Overload the !* operator.
152190
operator !* (a: Bigint, b: Bigint) -> Bigint {
153191
if a.width != b.width || a.isSigned != b.isSigned {
154-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
192+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
155193
}
156194
return Bigint(runtime.bigintMulTrunc(a.bigint, b.bigint))
157195
}
158196

159197
// Overload the / operator.
160198
operator / (a: Bigint, b: Bigint) -> Bigint {
161199
if a.width != b.width || a.isSigned != b.isSigned {
162-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
200+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
163201
}
164202
return Bigint(runtime.bigintDiv(a.bigint, b.bigint))
165203
}
166204

167205
// Overload the % operator.
168206
operator % (a: Bigint, b: Bigint) -> Bigint {
169207
if a.width != b.width || a.isSigned != b.isSigned {
170-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
208+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
171209
}
172210
return Bigint(runtime.bigintMod(a.bigint, b.bigint))
173211
}
174212

175213
// Overload the == operator.
176214
operator == (a: Bigint, b: Bigint) -> bool {
177215
if a.width != b.width || a.isSigned != b.isSigned {
178-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
216+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
179217
}
180218
return runtime.compareBigints(runtime.ComparisonType.Equal, a.bigint, b.bigint)
181219
}
182220

183221
// Overload the != operator.
184222
operator != (a: Bigint, b: Bigint) -> bool {
185223
if a.width != b.width || a.isSigned != b.isSigned {
186-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
224+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
187225
}
188226
return runtime.compareBigints(runtime.ComparisonType.NotEqual, a.bigint, b.bigint)
189227
}
190228

191229
// Overload the < operator.
192230
operator < (a: Bigint, b: Bigint) -> bool {
193231
if a.width != b.width || a.isSigned != b.isSigned {
194-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
232+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
195233
}
196234
return runtime.compareBigints(runtime.ComparisonType.Lt, a.bigint, b.bigint)
197235
}
198236

199237
// Overload the <= operator.
200238
operator <= (a: Bigint, b: Bigint) -> bool {
201239
if a.width != b.width || a.isSigned != b.isSigned {
202-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
240+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
203241
}
204242
return runtime.compareBigints(runtime.ComparisonType.Le, a.bigint, b.bigint)
205243
}
206244

207245
// Overload the > operator.
208246
operator > (a: Bigint, b: Bigint) -> bool {
209247
if a.width != b.width || a.isSigned != b.isSigned {
210-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
248+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
211249
}
212250
return runtime.compareBigints(runtime.ComparisonType.Gt, a.bigint, b.bigint)
213251
}
214252

215253
// Overload the >= operator.
216254
operator >= (a: Bigint, b: Bigint) -> bool {
217255
if a.width != b.width || a.isSigned != b.isSigned {
218-
throw "Integers have different types: ", a.toString(), " and ", b.toString()
256+
panic "Integers have different types: ", a.toString(), " and ", b.toString()
219257
}
220258
return runtime.compareBigints(runtime.ComparisonType.Ge, a.bigint, b.bigint)
221259
}
@@ -274,6 +312,34 @@ class Bigint(self, value: Int | Uint | runtime.BigintArray, width: u32 = 0u32) {
274312
operator ^ (a: Bigint, b: Bigint) -> Bigint {
275313
return Bigint(runtime.bigintBitwiseXor(a.bigint, b.bigint))
276314
}
315+
316+
// Overload the cast operator.
317+
operator <> (a: Bigint | Int | Uint, b: Bigint | Int | Uint) -> Bigint | Int | Uint {
318+
typeswitch a {
319+
Bigint => {
320+
typeswitch b {
321+
Int | Uint => return Bigint(b, a.width)
322+
Bigint => return b.cast(a.width, a.isSigned, b.isSecret, false)
323+
}
324+
}
325+
Int | Uint => {
326+
// b must be a Bigint
327+
val = b.resize(widthof(a), true)
328+
if val.resize(b.width) != b {
329+
panic "Bigint does not fit in ", widthof(a), " bits"
330+
}
331+
typeswitch a {
332+
Uint => {
333+
}
334+
Int => {
335+
val = val.toSigned()
336+
}
337+
}
338+
s = val.toStringLE()
339+
return s.toUintLE(typeof(a))
340+
}
341+
}
342+
}
277343
}
278344

279345
// Test printing and addition.
@@ -299,6 +365,12 @@ unittest testCasting {
299365
c = b + Bigint(1i32, 256u32)
300366
assert c.width == 256u32
301367
println c
368+
d = <c>123
369+
println "d = ", d
370+
e = <typeof(null(d))>0u32 // This dangerous cast converts 0 to null(Bigint).
371+
assert isnull(e)
372+
f = <b>a + b
373+
println "f = ", f
302374
}
303375

304376
// Test comparison operators.
@@ -386,3 +458,33 @@ unittest testBitwiseOperators {
386458
assert a | b == Bigint(0xffffu16)
387459
assert a ^ (b >> 1u32) == Bigint(0x7f7fu16)
388460
}
461+
462+
unittest testResize {
463+
a = Bigint(123)
464+
a.resize(32u32)
465+
println a
466+
}
467+
468+
unittest testToFromEncodedStrings {
469+
m1 = Bigint(2, 256u32) ** 255u32 - Bigint(19, 256u32)
470+
println "m1 = ", m1
471+
mStr = m1.toStringLE()
472+
m2 = Bigint.fromStringLE(mStr, 256u32, false)
473+
println "m2 = ", m2
474+
assert m1 == m2
475+
m3 = Bigint(-123i100)
476+
println "m3 = ", m3
477+
mStr = m3.toStringBE()
478+
m4 = Bigint.fromStringBE(mStr, 100u32, true)
479+
println "m4 = ", m4
480+
assert m3 == m4
481+
}
482+
483+
unittest testToSigned {
484+
val = Bigint(1, 2u32)
485+
println val
486+
signedVal = val.toSigned()
487+
signedVal = -signedVal
488+
println signedVal
489+
assert (-signedVal).toSigned(false) == val
490+
}

bootstrap/database/bigint.stdout

+9
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,14 @@ deadbeefu256
55
deadbef0u256
66
123i256 width = 256
77
124i256
8+
d = 123u256
9+
f = 246i256
810
-12345i32
911
aa555u20
12+
123u64
13+
m1 = 57896044618658097711785492504343953926634992332820282019728792003956564819949u256
14+
m2 = 57896044618658097711785492504343953926634992332820282019728792003956564819949u256
15+
m3 = -123i100
16+
m4 = -123i100
17+
1u2
18+
-1i2

0 commit comments

Comments
 (0)