From 4ace3f049da04a8ef27e2f75b03b72de284b55a3 Mon Sep 17 00:00:00 2001 From: zuckerberg Date: Tue, 13 Jul 2021 19:10:27 -0400 Subject: [PATCH] floats --- src/context.cpp | 76 +++++++++++----------- src/grammar.peg | 14 +--- src/main.cpp | 2 + src/types.cpp | 165 ++++++++++++++++++++++++++++++++++++++++-------- src/types.h | 66 +++++++++++-------- src/util.cpp | 4 +- 6 files changed, 224 insertions(+), 103 deletions(-) diff --git a/src/context.cpp b/src/context.cpp index fb5c07b..c18bb72 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -28,40 +28,40 @@ Value Context::eval(peg::Ast& ast) { for (int i=0; iwriteVar(cxt, identifier, value); - return Nil(); + return Value(cxt, Nil()); } else if (ast.name == "IDENTIFIER" || ast.name == "BUILTINIDENTIFIER") { - return Identifier(std::string(ast.token_to_string())); + return Value(cxt, Identifier(std::string(ast.token_to_string()))); } else if (ast.name == "INTEGER") { - // TODO parse hex, oct, and binary - return ast.token_to_number(); + return Value(cxt, ast.token_to_number()); + } else if (ast.name == "FLOAT") { + return Value(cxt, ast.token_to_number()); } else if (ast.name == "BUILTINCALL" ) { std::string identifier = eval(*nodes[0]).getIdentifier(cxt).identifier; Args args = eval(*nodes[1]).getArgs(cxt); return builtins.at(identifier).execute(cxt, args); } else if (ast.name == "STRINGLITERALSINGLE") { - return ast.token_to_string(); + return Value(cxt, ast.token_to_string()); } else if (ast.name == "ExprList") { Args exprs; for (int i=0; igetVar(*this, name); int op = (*nodes[1]).choice; auto v2 = getValue(eval(*nodes[2])); - Value result = Nil(); - // TODO: floats + Value result = Value(cxt, Nil()); if (op == 0) { - result = v1.getInt(cxt) * v2.getInt(cxt); + result = v1 * v2; } else if (op == 1) { - result = v1.getInt(cxt) % v2.getInt(cxt); + result = v1 % v2; } else if (op == 2) { - result = v1.getInt(cxt) + v2.getInt(cxt); + result = v1 + v2; } else if (op == 3) { - result = v1.getInt(cxt) - v2.getInt(cxt); + result = v1 - v2; } else if (op == 4) { - result = v1.getInt(cxt) & v2.getInt(cxt); + result = v1 & v2; } else if (op == 5) { - result = v1.getInt(cxt) ^ v2.getInt(cxt); + result = v1 ^ v2; } else if (op == 6) { - result = v1.getInt(cxt) | v2.getInt(cxt); + result = v1 | v2; } else if (op == 7) { result = v2; } @@ -107,12 +105,12 @@ Value Context::eval(peg::Ast& ast) { return result; } else if (ast.name == "PrimaryTypeExpr") { int op = ast.choice; - if (op == 8) { - return false; + if (op == 7) { + return Value(cxt, false); + } else if (op == 8) { + return Value(cxt, Nil()); } else if (op == 9) { - return Nil(); - } else if (op == 10) { - return true; + return Value(cxt, true); } } else if (ast.name == "CompareExpr") { Value v1 = getValue(eval(*nodes[0])); @@ -120,17 +118,17 @@ Value Context::eval(peg::Ast& ast) { Value v2 = getValue(eval(*nodes[2])); // TODO: floats, bool, etc. if (op == 0) { - return (bool)(v1.getInt(cxt) == v2.getInt(cxt)); + return v1 == v2; } else if (op == 1) { - return (bool)(v1.getInt(cxt) != v2.getInt(cxt)); + return v1 != v2; } else if (op == 2) { - return (bool)(v1.getInt(cxt) < v2.getInt(cxt)); + return v1 < v2; } else if (op == 3) { - return (bool)(v1.getInt(cxt) > v2.getInt(cxt)); + return v1 > v2; } else if (op == 4) { - return (bool)(v1.getInt(cxt) <= v2.getInt(cxt)); + return v1 <= v2; } else if (op == 5) { - return (bool)(v1.getInt(cxt) >= v2.getInt(cxt)); + return v1 >= v2; } } else if (ast.name == "IfStatement") { Value val = getValue(eval(*nodes[0])); @@ -141,13 +139,13 @@ Value Context::eval(peg::Ast& ast) { } } else if (ast.name == "Block") { // TODO create new scope - Value result = Nil(); + Value result = Value(cxt, Nil()); for (int i=0; i skip - / "0o" < oct_int > skip - / "0x" < hex_int > skip - / < dec_int > skip +INTEGER <- < dec_int > skip IDENTIFIER <- !keyword < [A-Za-z_] [A-Za-z0-9_]* > skip BUILTINIDENTIFIER <- "@" < [A-Za-z_][A-Za-z0-9_]* > skip -CHAR_LITERAL <- "'" char_char "'" skip FLOAT - <- "0x" hex_int "." hex_int ([pP] [-+]? dec_int)? skip - / dec_int "." dec_int ([eE] [-+]? dec_int)? skip - / "0x" hex_int "."? [pP] [-+]? dec_int skip - / dec_int "."? [eE] [-+]? dec_int skip + <- < dec_int "." dec_int ([eE] [-+]? dec_int)? > skip + / < dec_int "."? [eE] [-+]? dec_int > skip STRINGLITERAL <- STRINGLITERALSINGLE diff --git a/src/main.cpp b/src/main.cpp index 5eaabb8..00a5c15 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,8 @@ int main(void) { @print(abc); }; hello("world"); + a = 0.1 / 100; + @print(a); )"; parser.enable_ast(); diff --git a/src/types.cpp b/src/types.cpp index dbd2acb..955423c 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -7,7 +7,7 @@ Value Func::execute(Context& cxt, Args& args) { return nativeFunction(cxt, args); } else { // TODO create scope - Value result = Value(Nil()); + Value result = Value(cxt, Nil()); for (int i=0; iwriteVar(cxt, argNames[i].identifier, args.args[i]); } @@ -17,32 +17,32 @@ Value Func::execute(Context& cxt, Args& args) { } } -Value::Value(Nil nil) : type(TypeNil) { +Value::Value(Context &cxt, Nil nil) : cxt(cxt), type(TypeNil) { value.nil = Nil(); } -Value::Value(long int_) : type(TypeInt) { +Value::Value(Context &cxt, long int_) : cxt(cxt), type(TypeInt) { value.int_ = int_; } -Value::Value(double float_) : type(TypeFloat) { +Value::Value(Context &cxt, double float_) : cxt(cxt), type(TypeFloat) { value.float_ = float_; } -Value::Value(bool bool_) : type(TypeBoolean) { +Value::Value(Context &cxt, bool bool_) : cxt(cxt), type(TypeBoolean) { value.bool_ = bool_; } -Value::Value(const std::string &string) : type(TypeString) { +Value::Value(Context &cxt, const std::string &string) : cxt(cxt), type(TypeString) { value.string = new std::string(string); } -Value::Value(const Func &function) : type(TypeFunction) { +Value::Value(Context &cxt, const Func &function) : cxt(cxt), type(TypeFunction) { value.function = new Func(function); } -Value::Value(const Args &args) : type(TypeArgs) { +Value::Value(Context &cxt, const Args &args) : cxt(cxt), type(TypeArgs) { value.args = new Args(args); } -Value::Value(const Identifier &identifier) : type(TypeIdentifier) { +Value::Value(Context &cxt, const Identifier &identifier) : cxt(cxt), type(TypeIdentifier) { value.identifier = new Identifier(identifier); } -Value::Value(const Value &val) { +Value::Value(const Value &val) : cxt(val.cxt) { if (val.isNil()) { *this = Nil(); } else if (val.isInt()) { @@ -178,87 +178,198 @@ bool Value::isIdentifier() const { return type == TypeIdentifier; } -void Value::assertNil(Context &cxt) { +void Value::assertNil(Context &cxt) const { if (!isNil()) { cxt.error("value is not nil"); } } -void Value::assertInt(Context &cxt) { +void Value::assertInt(Context &cxt) const { if (!isInt()) { cxt.error("value is not an integer"); } } -void Value::assertFloat(Context &cxt) { +void Value::assertFloat(Context &cxt) const { if (!isFloat()) { cxt.error("value is not a float"); } } -void Value::assertNumber(Context &cxt) { +void Value::assertNumber(Context &cxt) const { if (!isNumber()) { cxt.error("value is not a number"); } } -void Value::assertBoolean(Context &cxt) { +void Value::assertBoolean(Context &cxt) const { if (!isBoolean()) { cxt.error("value is not a boolean"); } } -void Value::assertString(Context &cxt) { +void Value::assertString(Context &cxt) const { if (!isString()) { cxt.error("value is not a string"); } } -void Value::assertFunction(Context &cxt) { +void Value::assertFunction(Context &cxt) const { if (!isFunction()) { cxt.error("value is not a function"); } } -void Value::assertArgs(Context &cxt) { +void Value::assertArgs(Context &cxt) const { if (!isArgs()) { cxt.error("value is not arguments"); } } -void Value::assertIdentifier(Context &cxt) { +void Value::assertIdentifier(Context &cxt) const { if (!isIdentifier()) { cxt.error("value is not identifier"); } } -Nil Value::getNil(Context &cxt) { +Nil Value::getNil(Context &cxt) const { assertNil(cxt); return value.nil; } -long Value::getInt(Context &cxt) { +long Value::getInt(Context &cxt) const { assertNumber(cxt); if (isFloat()) return (long)value.float_; else return value.int_; } -double Value::getFloat(Context &cxt) { +double Value::getFloat(Context &cxt) const { assertNumber(cxt); if (isInt()) return (double)value.int_; else return value.float_; } -bool Value::getBoolean(Context &cxt) { +bool Value::getBoolean(Context &cxt) const { assertBoolean(cxt); return value.bool_; } -std::string Value::getString(Context &cxt) { +std::string Value::getString(Context &cxt) const { assertString(cxt); return *value.string; } -Func Value::getFunction(Context &cxt) { +Func Value::getFunction(Context &cxt) const { assertFunction(cxt); return *value.function; } -Args Value::getArgs(Context &cxt) { +Args Value::getArgs(Context &cxt) const { assertArgs(cxt); return *value.args; } -Identifier Value::getIdentifier(Context &cxt) { +Identifier Value::getIdentifier(Context &cxt) const { assertIdentifier(cxt); return *value.identifier; +} + +Value Value::operator+(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) + rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) + rhs.getInt(cxt)); + } +} +Value Value::operator-(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) - rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) - rhs.getInt(cxt)); + } +} +Value Value::operator*(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) * rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) * rhs.getInt(cxt)); + } +} +Value Value::operator/(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) / rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) / rhs.getInt(cxt)); + } +} +Value Value::operator%(const Value &rhs) const { + assertInt(cxt); + rhs.assertInt(cxt); + return Value(cxt, getInt(cxt) % rhs.getInt(cxt)); +} +Value Value::operator&(const Value &rhs) const { + assertInt(cxt); + rhs.assertInt(cxt); + return Value(cxt, getInt(cxt) & rhs.getInt(cxt)); +} +Value Value::operator^(const Value &rhs) const { + assertInt(cxt); + rhs.assertInt(cxt); + return Value(cxt, getInt(cxt) ^ rhs.getInt(cxt)); +} +Value Value::operator|(const Value &rhs) const { + assertInt(cxt); + rhs.assertInt(cxt); + return Value(cxt, getInt(cxt) | rhs.getInt(cxt)); +} +Value Value::operator==(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) == rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) == rhs.getInt(cxt)); + } +} +Value Value::operator!=(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) != rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) != rhs.getInt(cxt)); + } +} +Value Value::operator<(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) < rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) < rhs.getInt(cxt)); + } +} +Value Value::operator>(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) > rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) > rhs.getInt(cxt)); + } +} +Value Value::operator<=(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) <= rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) <= rhs.getInt(cxt)); + } +} +Value Value::operator>=(const Value &rhs) const { + assertNumber(cxt); + rhs.assertNumber(cxt); + if (isFloat() || rhs.isFloat()) { + return Value(cxt, getFloat(cxt) >= rhs.getFloat(cxt)); + } else { + return Value(cxt, getInt(cxt) >= rhs.getInt(cxt)); + } } \ No newline at end of file diff --git a/src/types.h b/src/types.h index 2987759..3a1db85 100644 --- a/src/types.h +++ b/src/types.h @@ -81,16 +81,17 @@ protected: Type type = TypeNil; TypeValues value; + Context &cxt; public: - Value(Nil nil); - Value(long int_); - Value(double float_); - Value(bool bool_); - Value(const std::string &string); - Value(const Func &function); - Value(const Args &args); - Value(const Identifier &identifier); + Value(Context &cxt, Nil nil); + Value(Context &cxt, long int_); + Value(Context &cxt, double float_); + Value(Context &cxt, bool bool_); + Value(Context &cxt, const std::string &string); + Value(Context &cxt, const Func &function); + Value(Context &cxt, const Args &args); + Value(Context &cxt, const Identifier &identifier); Value(const Value &value); Value& operator=(const Value &rhs); @@ -117,22 +118,37 @@ public: bool isArgs() const; bool isIdentifier() const; - void assertNil(Context &cxt); - void assertInt(Context &cxt); - void assertFloat(Context &cxt); - void assertNumber(Context &cxt); - void assertBoolean(Context &cxt); - void assertString(Context &cxt); - void assertFunction(Context &cxt); - void assertArgs(Context &cxt); - void assertIdentifier(Context &cxt); + void assertNil(Context &cxt) const; + void assertInt(Context &cxt) const; + void assertFloat(Context &cxt) const; + void assertNumber(Context &cxt) const; + void assertBoolean(Context &cxt) const; + void assertString(Context &cxt) const; + void assertFunction(Context &cxt) const; + void assertArgs(Context &cxt) const; + void assertIdentifier(Context &cxt) const; - Nil getNil(Context &cxt); - long getInt(Context &cxt); - double getFloat(Context &cxt); - bool getBoolean(Context &cxt); - std::string getString(Context &cxt); - Func getFunction(Context &cxt); - Args getArgs(Context &cxt); - Identifier getIdentifier(Context &cxt); + Nil getNil(Context &cxt) const; + long getInt(Context &cxt) const; + double getFloat(Context &cxt) const; + bool getBoolean(Context &cxt) const; + std::string getString(Context &cxt) const; + Func getFunction(Context &cxt) const; + Args getArgs(Context &cxt) const; + Identifier getIdentifier(Context &cxt) const; + + Value operator+(const Value &rhs) const; + Value operator-(const Value &rhs) const; + Value operator*(const Value &rhs) const; + Value operator/(const Value &rhs) const; + Value operator%(const Value &rhs) const; + Value operator&(const Value &rhs) const; + Value operator^(const Value &rhs) const; + Value operator|(const Value &rhs) const; + Value operator==(const Value &rhs) const; + Value operator!=(const Value &rhs) const; + Value operator<(const Value &rhs) const; + Value operator>(const Value &rhs) const; + Value operator<=(const Value &rhs) const; + Value operator>=(const Value &rhs) const; }; \ No newline at end of file diff --git a/src/util.cpp b/src/util.cpp index b81e6dc..bc5c6da 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -20,10 +20,12 @@ Value BuiltinFunctions::print(Context& cxt, Args& args) { std::cout << "false" << '\t'; } else if (var.isNil()) { std::cout << "nil" << '\t'; + } else if (var.isFloat()) { + std::cout << var.getFloat(cxt) << std::endl; } else { cxt.error("Attempt to print unsupported type"); } } std::cout << std::endl; - return Nil(); + return Value(cxt, Nil()); } \ No newline at end of file