Skip to content

Commit

Permalink
Added Boolean and Null type and Global Constant Variables
Browse files Browse the repository at this point in the history
Also added better error handling in SymbolTable::set()
Also fixed `warning C4715: 'Interpreter::visit': not all control paths return a value`
  • Loading branch information
Samathingamajig committed Feb 21, 2021
1 parent ac1342e commit 708b3f1
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 19 deletions.
2 changes: 1 addition & 1 deletion BarkScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "interpreter/interpreter.h"
#include "context/context.h"

const std::string bsversion = "0.1.1";
const std::string bsversion = "0.1.2";

int main() {
std::cout << "BarkScript version " << bsversion << std::endl;
Expand Down
14 changes: 9 additions & 5 deletions interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ RuntimeResult Interpreter::visit(spNode node, spContext context) {
} else if (type == nodetypes::UnaryOperator) {
return visitUnaryOperatorNode(node, context);
} else {
std::cout << "Error: node type " + type + " does not have a visit method!" << std::endl;
return RuntimeResult().failure(makeSharedError(RuntimeError(node->positionStart, node->positionEnd, "Error: node type " + type + " does not have a visit method!", context)));
}
}

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

RuntimeResult Interpreter::visitVariableRetrievementNode(spNode node, spContext context) {
Expand Down
219 changes: 211 additions & 8 deletions object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ bool didUnderflow(double value) {
}

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

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

RuntimeResult Object::toOther(spObject other) {
std::string type = other->type;

if (type == "Number") {
return this->toNumber();
} else if (type == "Boolean") {
return this->toBoolean();
} else if (type == "Null") {
return this->toNull();
} else {
return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "No conversion from " + this->type + " to " + other->type + " exists!", this->context)));
}
}

RuntimeResult Object::toNull() {
return RuntimeResult().success(makeSharedObject(Null()));
}

Number::Number(double value, bool sign) {
this->type = "Number";
this->doubleValue = value;
Expand Down Expand Up @@ -82,7 +101,14 @@ spObject Number::copy() {
RuntimeResult Number::binary_plus(spObject other) {
RuntimeResult rt;

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_plus");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_plus", rt.error->details);
} else {
other = tempOther;
}
}

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

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_minus");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_minus", rt.error->details);
} else {
other = tempOther;
}
}

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

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_asterisk");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_asterisk", rt.error->details);
} else {
other = tempOther;
}
}

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

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_f_slash");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_f_slash", rt.error->details);
} else {
other = tempOther;
}
}

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

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_double_asterisk");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_double_asterisk", rt.error->details);
} else {
other = tempOther;
}
}

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

if (other->type != objecttypes::Number) return notImplemented(rt, this, other, "binary_double_f_slash");
if (other->type != objecttypes::Number) {
spObject tempOther = rt.registerRT(other->toNumber());
if (rt.hasError()) {
return notImplemented(rt, this, other, "binary_double_f_slash", rt.error->details);
} else {
other = tempOther;
}
}

if (other->isPureZero) return rt.failure(makeSharedError(RuntimeError(other->positionStart, other->positionEnd, "Floored division by 0", this->context)));
spObject normalDivisionResult = rt.registerRT(this->binary_f_slash(other));
Expand All @@ -206,3 +267,145 @@ RuntimeResult Number::unary_minus() {
else if (isInfinity) return rt.success(makeSharedObject(Number("Infinity", !sign)));
return rt.success(makeSharedObject(Number(this->doubleValue * -1)));
}

RuntimeResult Number::toNumber() {
return RuntimeResult().success(makeSharedObject(*this));
}

RuntimeResult Number::toBoolean() {
return RuntimeResult().success(makeSharedObject(Boolean(!(this->isPureZero || this->isNaN))));
}

Boolean::Boolean(bool value) {
this->type = "Boolean";
this->isPureDouble = true;
this->isPureZero = !value;
this->doubleValue = value;
}

std::string Boolean::to_string() {
return this->isPureZero ? "false" : "true";
}

spObject Boolean::copy() {
return makeSharedObject(Boolean(this->doubleValue));
}

RuntimeResult Boolean::toNumber() {
return RuntimeResult().success(makeSharedObject(Number(this->doubleValue)));
}

RuntimeResult Boolean::toBoolean() {
return RuntimeResult().success(makeSharedObject(*this));
}

std::string Null::to_string() {
return "null";
}

spObject Null::copy() {
return makeSharedObject(Null());
}

RuntimeResult Null::binary_plus(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_plus(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_plus", rt.error->details);
return self->binary_plus(other);
}

RuntimeResult Null::binary_minus(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_minus(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_minus", rt.error->details);
return self->binary_minus(other);
}

RuntimeResult Null::binary_asterisk(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_asterisk(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_asterisk", rt.error->details);
return self->binary_asterisk(other);
}

RuntimeResult Null::binary_f_slash(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_f_slash(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_f_slash", rt.error->details);
return self->binary_f_slash(other);
}

RuntimeResult Null::binary_double_asterisk(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_double_asterisk(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_double_asterisk", rt.error->details);
return self->binary_double_asterisk(other);
}

RuntimeResult Null::binary_double_f_slash(spObject other) {
RuntimeResult rt;
if (other->type == "Null") {
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
spObject tempOther = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->binary_double_f_slash(tempOther);
}
spObject self = rt.registerRT(this->toOther(other));
if (rt.hasError()) return notImplemented(rt, this, other, "binary_double_f_slash", rt.error->details);
return self->binary_double_f_slash(other);
}

RuntimeResult Null::unary_plus() {
return this->toNumber();
}

RuntimeResult Null::unary_minus() {
RuntimeResult rt;
spObject self = rt.registerRT(this->toNumber());
if (rt.hasError()) return rt;
return self->unary_minus();
}

RuntimeResult Null::toNumber() {
return RuntimeResult().success(makeSharedObject(Number(0)));
}

RuntimeResult Null::toBoolean() {
return RuntimeResult().success(makeSharedObject(Boolean(false)));
}
39 changes: 39 additions & 0 deletions object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ struct Object {

RuntimeResult virtual unary_plus() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "unary_plus for " + this->type + " is not implemented!", this->context))); };
RuntimeResult virtual unary_minus() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "unary_minus for " + this->type + " is not implemented!", this->context))); };

RuntimeResult toOther(spObject other);
RuntimeResult virtual toNumber() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "toNumber for " + this->type + " is not implemented!", this->context))); }
RuntimeResult virtual toBoolean() { return RuntimeResult().failure(makeSharedError(RuntimeError(this->positionStart, this->positionEnd, "toBoolean for " + this->type + " is not implemented!", this->context))); }
RuntimeResult toNull();
};

struct Number : Object {
Expand All @@ -76,6 +81,40 @@ struct Number : Object {

RuntimeResult unary_plus() override;
RuntimeResult unary_minus() override;

RuntimeResult toNumber() override;
RuntimeResult toBoolean() override;
};

struct Boolean : Number {
Boolean() { this->type = "Boolean"; this->isPureZero = 0; this->isPureDouble = true; }
Boolean(bool value);

std::string to_string() override;
spObject copy() override;

RuntimeResult toNumber() override;
RuntimeResult toBoolean() override;
};

struct Null : Object {
Null() { this->type = "Null"; }

std::string to_string() override;
spObject copy() override;

RuntimeResult binary_plus(spObject other) override;
RuntimeResult binary_minus(spObject other) override;
RuntimeResult binary_asterisk(spObject other) override;
RuntimeResult binary_f_slash(spObject other) override;
RuntimeResult binary_double_asterisk(spObject other) override;
RuntimeResult binary_double_f_slash(spObject other) override;

RuntimeResult unary_plus() override;
RuntimeResult unary_minus() override;

RuntimeResult toNumber() override;
RuntimeResult toBoolean() override;
};

#endif // !OBJECT_H
Loading

0 comments on commit 708b3f1

Please sign in to comment.