Skip to content

Commit 708b3f1

Browse files
Added Boolean and Null type and Global Constant Variables
Also added better error handling in SymbolTable::set() Also fixed `warning C4715: 'Interpreter::visit': not all control paths return a value`
1 parent ac1342e commit 708b3f1

6 files changed

Lines changed: 293 additions & 19 deletions

File tree

BarkScript.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "interpreter/interpreter.h"
99
#include "context/context.h"
1010

11-
const std::string bsversion = "0.1.1";
11+
const std::string bsversion = "0.1.2";
1212

1313
int main() {
1414
std::cout << "BarkScript version " << bsversion << std::endl;

interpreter/Interpreter.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ RuntimeResult Interpreter::visit(spNode node, spContext context) {
4242
} else if (type == nodetypes::UnaryOperator) {
4343
return visitUnaryOperatorNode(node, context);
4444
} else {
45-
std::cout << "Error: node type " + type + " does not have a visit method!" << std::endl;
45+
return RuntimeResult().failure(makeSharedError(RuntimeError(node->positionStart, node->positionEnd, "Error: node type " + type + " does not have a visit method!", context)));
4646
}
4747
}
4848

@@ -58,10 +58,14 @@ RuntimeResult Interpreter::visitVariableAssignmentNode(spNode node, spContext co
5858
std::string variableName = node->token.value;
5959
spObject value = rt.registerRT(visit(node->valueNode, context));
6060
if (rt.hasError()) return rt;
61-
bool success = context->symbolTable->set(variableName, value, true);
62-
if (!success)
63-
return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "Variable not reassigned properly", context)));
64-
return rt.success(value);
61+
SymbolTableSetReturnCode success = context->symbolTable->set(variableName, value, true);
62+
switch (success) {
63+
case SymbolTableSetReturnCode::perfect: { return rt.success(value); }
64+
case SymbolTableSetReturnCode::errorGlobalConstantVariable: { return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "You cannot modify a global constant variable!", context))); }
65+
case SymbolTableSetReturnCode::errorUserDefinedConstantVariable: { return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "You cannot modify a constant variable!", context))); }
66+
case SymbolTableSetReturnCode::errorNotInScope: { return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "Variable " + variableName + " does not exist in the current scope!", context))); }
67+
default: { return rt.failure(makeSharedError(RuntimeError(node->token.positionStart, node->positionEnd, "Unknown return value when setting: " + std::to_string((int) success), context))); }
68+
}
6569
}
6670

6771
RuntimeResult Interpreter::visitVariableRetrievementNode(spNode node, spContext context) {

object/Object.cpp

Lines changed: 211 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ bool didUnderflow(double value) {
1212
}
1313

1414
template <class T>
15-
RuntimeResult notImplemented(RuntimeResult rt, T self, spObject other, std::string function) {
16-
return rt.failure(makeSharedError(RuntimeError(self->positionStart, other->positionEnd, function + " is not implemented between " + self->type + " and " + other->type + "!", self->context)));
15+
RuntimeResult notImplemented(RuntimeResult rt, T self, spObject other, std::string function, std::string extra = "") {
16+
extra = extra.size() > 0 ? " (" + extra + ")" : "";
17+
return rt.failure(makeSharedError(RuntimeError(self->positionStart, other->positionEnd, function + " is not implemented between " + self->type + " and " + other->type + "!" + extra, self->context)));
1718
}
1819

1920
void Object::setPosition(Position positionStart, Position positionEnd) {
@@ -25,6 +26,24 @@ void Object::setContext(spContext context) {
2526
this->context = context;
2627
}
2728

29+
RuntimeResult Object::toOther(spObject other) {
30+
std::string type = other->type;
31+
32+
if (type == "Number") {
33+
return this->toNumber();
34+
} else if (type == "Boolean") {
35+
return this->toBoolean();
36+
} else if (type == "Null") {
37+
return this->toNull();
38+
} else {
39+
return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "No conversion from " + this->type + " to " + other->type + " exists!", this->context)));
40+
}
41+
}
42+
43+
RuntimeResult Object::toNull() {
44+
return RuntimeResult().success(makeSharedObject(Null()));
45+
}
46+
2847
Number::Number(double value, bool sign) {
2948
this->type = "Number";
3049
this->doubleValue = value;
@@ -82,7 +101,14 @@ spObject Number::copy() {
82101
RuntimeResult Number::binary_plus(spObject other) {
83102
RuntimeResult rt;
84103

85-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_plus");
104+
if (other->type != objecttypes::Number) {
105+
spObject tempOther = rt.registerRT(other->toNumber());
106+
if (rt.hasError()) {
107+
return notImplemented(rt, this, other, "binary_plus", rt.error->details);
108+
} else {
109+
other = tempOther;
110+
}
111+
}
86112

87113
if (this->isNaN || other->isNaN) return rt.success(makeSharedObject(Number("NaN")));
88114
if (this->isInfinity || other->isInfinity) {
@@ -103,7 +129,14 @@ RuntimeResult Number::binary_plus(spObject other) {
103129
RuntimeResult Number::binary_minus(spObject other) {
104130
RuntimeResult rt;
105131

106-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_minus");
132+
if (other->type != objecttypes::Number) {
133+
spObject tempOther = rt.registerRT(other->toNumber());
134+
if (rt.hasError()) {
135+
return notImplemented(rt, this, other, "binary_minus", rt.error->details);
136+
} else {
137+
other = tempOther;
138+
}
139+
}
107140

108141
if (this->isNaN || other->isNaN) return rt.success(makeSharedObject(Number("NaN")));
109142
if (this->isInfinity || other->isInfinity) {
@@ -124,7 +157,14 @@ RuntimeResult Number::binary_minus(spObject other) {
124157
RuntimeResult Number::binary_asterisk(spObject other) {
125158
RuntimeResult rt;
126159

127-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_asterisk");
160+
if (other->type != objecttypes::Number) {
161+
spObject tempOther = rt.registerRT(other->toNumber());
162+
if (rt.hasError()) {
163+
return notImplemented(rt, this, other, "binary_asterisk", rt.error->details);
164+
} else {
165+
other = tempOther;
166+
}
167+
}
128168

129169
if (this->isNaN || other->isNaN) return rt.success(makeSharedObject(Number("NaN")));
130170
if (this->isInfinity || other->isInfinity) {
@@ -146,7 +186,14 @@ RuntimeResult Number::binary_asterisk(spObject other) {
146186
RuntimeResult Number::binary_f_slash(spObject other) {
147187
RuntimeResult rt;
148188

149-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_f_slash");
189+
if (other->type != objecttypes::Number) {
190+
spObject tempOther = rt.registerRT(other->toNumber());
191+
if (rt.hasError()) {
192+
return notImplemented(rt, this, other, "binary_f_slash", rt.error->details);
193+
} else {
194+
other = tempOther;
195+
}
196+
}
150197

151198
if (other->isPureZero) return rt.failure(makeSharedError(RuntimeError(other->positionStart, other->positionEnd, "Division by 0", this->context)));
152199
if (this->isNaN || other->isNaN) return rt.success(makeSharedObject(Number("NaN")));
@@ -162,7 +209,14 @@ RuntimeResult Number::binary_f_slash(spObject other) {
162209
RuntimeResult Number::binary_double_asterisk(spObject other) {
163210
RuntimeResult rt;
164211

165-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_double_asterisk");
212+
if (other->type != objecttypes::Number) {
213+
spObject tempOther = rt.registerRT(other->toNumber());
214+
if (rt.hasError()) {
215+
return notImplemented(rt, this, other, "binary_double_asterisk", rt.error->details);
216+
} else {
217+
other = tempOther;
218+
}
219+
}
166220

167221
if (this->isNaN || other->isNaN) return rt.success(makeSharedObject(Number("NaN")));
168222
if (other->isPureZero) return rt.success(makeSharedObject(Number(1)));
@@ -179,7 +233,14 @@ RuntimeResult Number::binary_double_asterisk(spObject other) {
179233
RuntimeResult Number::binary_double_f_slash(spObject other) {
180234
RuntimeResult rt;
181235

182-
if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_double_f_slash");
236+
if (other->type != objecttypes::Number) {
237+
spObject tempOther = rt.registerRT(other->toNumber());
238+
if (rt.hasError()) {
239+
return notImplemented(rt, this, other, "binary_double_f_slash", rt.error->details);
240+
} else {
241+
other = tempOther;
242+
}
243+
}
183244

184245
if (other->isPureZero) return rt.failure(makeSharedError(RuntimeError(other->positionStart, other->positionEnd, "Floored division by 0", this->context)));
185246
spObject normalDivisionResult = rt.registerRT(this->binary_f_slash(other));
@@ -206,3 +267,145 @@ RuntimeResult Number::unary_minus() {
206267
else if (isInfinity) return rt.success(makeSharedObject(Number("Infinity", !sign)));
207268
return rt.success(makeSharedObject(Number(this->doubleValue * -1)));
208269
}
270+
271+
RuntimeResult Number::toNumber() {
272+
return RuntimeResult().success(makeSharedObject(*this));
273+
}
274+
275+
RuntimeResult Number::toBoolean() {
276+
return RuntimeResult().success(makeSharedObject(Boolean(!(this->isPureZero || this->isNaN))));
277+
}
278+
279+
Boolean::Boolean(bool value) {
280+
this->type = "Boolean";
281+
this->isPureDouble = true;
282+
this->isPureZero = !value;
283+
this->doubleValue = value;
284+
}
285+
286+
std::string Boolean::to_string() {
287+
return this->isPureZero ? "false" : "true";
288+
}
289+
290+
spObject Boolean::copy() {
291+
return makeSharedObject(Boolean(this->doubleValue));
292+
}
293+
294+
RuntimeResult Boolean::toNumber() {
295+
return RuntimeResult().success(makeSharedObject(Number(this->doubleValue)));
296+
}
297+
298+
RuntimeResult Boolean::toBoolean() {
299+
return RuntimeResult().success(makeSharedObject(*this));
300+
}
301+
302+
std::string Null::to_string() {
303+
return "null";
304+
}
305+
306+
spObject Null::copy() {
307+
return makeSharedObject(Null());
308+
}
309+
310+
RuntimeResult Null::binary_plus(spObject other) {
311+
RuntimeResult rt;
312+
if (other->type == "Null") {
313+
spObject self = rt.registerRT(this->toNumber());
314+
if (rt.hasError()) return rt;
315+
spObject tempOther = rt.registerRT(this->toNumber());
316+
if (rt.hasError()) return rt;
317+
return self->binary_plus(tempOther);
318+
}
319+
spObject self = rt.registerRT(this->toOther(other));
320+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_plus", rt.error->details);
321+
return self->binary_plus(other);
322+
}
323+
324+
RuntimeResult Null::binary_minus(spObject other) {
325+
RuntimeResult rt;
326+
if (other->type == "Null") {
327+
spObject self = rt.registerRT(this->toNumber());
328+
if (rt.hasError()) return rt;
329+
spObject tempOther = rt.registerRT(this->toNumber());
330+
if (rt.hasError()) return rt;
331+
return self->binary_minus(tempOther);
332+
}
333+
spObject self = rt.registerRT(this->toOther(other));
334+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_minus", rt.error->details);
335+
return self->binary_minus(other);
336+
}
337+
338+
RuntimeResult Null::binary_asterisk(spObject other) {
339+
RuntimeResult rt;
340+
if (other->type == "Null") {
341+
spObject self = rt.registerRT(this->toNumber());
342+
if (rt.hasError()) return rt;
343+
spObject tempOther = rt.registerRT(this->toNumber());
344+
if (rt.hasError()) return rt;
345+
return self->binary_asterisk(tempOther);
346+
}
347+
spObject self = rt.registerRT(this->toOther(other));
348+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_asterisk", rt.error->details);
349+
return self->binary_asterisk(other);
350+
}
351+
352+
RuntimeResult Null::binary_f_slash(spObject other) {
353+
RuntimeResult rt;
354+
if (other->type == "Null") {
355+
spObject self = rt.registerRT(this->toNumber());
356+
if (rt.hasError()) return rt;
357+
spObject tempOther = rt.registerRT(this->toNumber());
358+
if (rt.hasError()) return rt;
359+
return self->binary_f_slash(tempOther);
360+
}
361+
spObject self = rt.registerRT(this->toOther(other));
362+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_f_slash", rt.error->details);
363+
return self->binary_f_slash(other);
364+
}
365+
366+
RuntimeResult Null::binary_double_asterisk(spObject other) {
367+
RuntimeResult rt;
368+
if (other->type == "Null") {
369+
spObject self = rt.registerRT(this->toNumber());
370+
if (rt.hasError()) return rt;
371+
spObject tempOther = rt.registerRT(this->toNumber());
372+
if (rt.hasError()) return rt;
373+
return self->binary_double_asterisk(tempOther);
374+
}
375+
spObject self = rt.registerRT(this->toOther(other));
376+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_double_asterisk", rt.error->details);
377+
return self->binary_double_asterisk(other);
378+
}
379+
380+
RuntimeResult Null::binary_double_f_slash(spObject other) {
381+
RuntimeResult rt;
382+
if (other->type == "Null") {
383+
spObject self = rt.registerRT(this->toNumber());
384+
if (rt.hasError()) return rt;
385+
spObject tempOther = rt.registerRT(this->toNumber());
386+
if (rt.hasError()) return rt;
387+
return self->binary_double_f_slash(tempOther);
388+
}
389+
spObject self = rt.registerRT(this->toOther(other));
390+
if (rt.hasError()) return notImplemented(rt, this, other, "binary_double_f_slash", rt.error->details);
391+
return self->binary_double_f_slash(other);
392+
}
393+
394+
RuntimeResult Null::unary_plus() {
395+
return this->toNumber();
396+
}
397+
398+
RuntimeResult Null::unary_minus() {
399+
RuntimeResult rt;
400+
spObject self = rt.registerRT(this->toNumber());
401+
if (rt.hasError()) return rt;
402+
return self->unary_minus();
403+
}
404+
405+
RuntimeResult Null::toNumber() {
406+
return RuntimeResult().success(makeSharedObject(Number(0)));
407+
}
408+
409+
RuntimeResult Null::toBoolean() {
410+
return RuntimeResult().success(makeSharedObject(Boolean(false)));
411+
}

object/object.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ struct Object {
5757

5858
RuntimeResult virtual unary_plus() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "unary_plus for " + this->type + " is not implemented!", this->context))); };
5959
RuntimeResult virtual unary_minus() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "unary_minus for " + this->type + " is not implemented!", this->context))); };
60+
61+
RuntimeResult toOther(spObject other);
62+
RuntimeResult virtual toNumber() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "toNumber for " + this->type + " is not implemented!", this->context))); }
63+
RuntimeResult virtual toBoolean() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "toBoolean for " + this->type + " is not implemented!", this->context))); }
64+
RuntimeResult toNull();
6065
};
6166

6267
struct Number : Object {
@@ -76,6 +81,40 @@ struct Number : Object {
7681

7782
RuntimeResult unary_plus() override;
7883
RuntimeResult unary_minus() override;
84+
85+
RuntimeResult toNumber() override;
86+
RuntimeResult toBoolean() override;
87+
};
88+
89+
struct Boolean : Number {
90+
Boolean() { this->type = "Boolean"; this->isPureZero = 0; this->isPureDouble = true; }
91+
Boolean(bool value);
92+
93+
std::string to_string() override;
94+
spObject copy() override;
95+
96+
RuntimeResult toNumber() override;
97+
RuntimeResult toBoolean() override;
98+
};
99+
100+
struct Null : Object {
101+
Null() { this->type = "Null"; }
102+
103+
std::string to_string() override;
104+
spObject copy() override;
105+
106+
RuntimeResult binary_plus(spObject other) override;
107+
RuntimeResult binary_minus(spObject other) override;
108+
RuntimeResult binary_asterisk(spObject other) override;
109+
RuntimeResult binary_f_slash(spObject other) override;
110+
RuntimeResult binary_double_asterisk(spObject other) override;
111+
RuntimeResult binary_double_f_slash(spObject other) override;
112+
113+
RuntimeResult unary_plus() override;
114+
RuntimeResult unary_minus() override;
115+
116+
RuntimeResult toNumber() override;
117+
RuntimeResult toBoolean() override;
79118
};
80119

81120
#endif // !OBJECT_H

0 commit comments

Comments
 (0)