diff --git a/src/Ast/Expressions/InitExpr.hpp b/src/Ast/Expressions/InitExpr.hpp index 0f76c0a..a81ae86 100644 --- a/src/Ast/Expressions/InitExpr.hpp +++ b/src/Ast/Expressions/InitExpr.hpp @@ -7,7 +7,7 @@ namespace Fig::Ast class InitExprAst final : public ExpressionAst { public: - FString structName; + Expression structe; std::vector> args; @@ -30,8 +30,8 @@ namespace Fig::Ast type = AstType::InitExpr; } - InitExprAst(FString _structName, std::vector> _args, InitMode _initMode) : - structName(std::move(_structName)), args(std::move(_args)), initMode(_initMode) + InitExprAst(Expression _structe, std::vector> _args, InitMode _initMode) : + structe(std::move(_structe)), args(std::move(_args)), initMode(_initMode) { type = AstType::InitExpr; } diff --git a/src/Ast/astBase.hpp b/src/Ast/astBase.hpp index 76aceb1..a5b1016 100644 --- a/src/Ast/astBase.hpp +++ b/src/Ast/astBase.hpp @@ -238,9 +238,11 @@ namespace Fig::Ast }; static const std::unordered_set unaryOps{ - Operator::Not, - Operator::Subtract, - Operator::BitNot, + Operator::Not, // ! + Operator::Subtract, // - + Operator::BitNot, // ~ + + Operator::BitAnd, // reference operator & }; static const std::unordered_set binaryOps{ Operator::Add, diff --git a/src/Bytecode/Bytecode.hpp b/src/Bytecode/Bytecode.hpp new file mode 100644 index 0000000..4f3c01d --- /dev/null +++ b/src/Bytecode/Bytecode.hpp @@ -0,0 +1,125 @@ +#pragma once + +/* + +从树遍历到虚拟机! + +*/ + +#include "Core/fig_string.hpp" +#include "Utils/magic_enum/magic_enum.hpp" +#include +#include +#include + +namespace Fig +{ + using OpCodeType = uint8_t; + enum class Bytecode : OpCodeType + { + HALT = 0x01, // 程序终止,后跟 8 位退出码 + + POP = 0x10, + + LOAD_NULL = 0x20, + LOAD_TRUE = 0x21, + LOAD_FALSE = 0x22, + LOAD_CON8 = 0x23, // 跟 8 位索引 (0 - 255) + LOAD_CON16 = 0x24, // 跟 16 位索引 (255 - 65535) + LOAD_CON32 = 0x25, // 跟 32 位索引 (65536 - 2^32-1) + + ADD = 0x30, // + + SUB = 0x31, // - + MUL = 0x32, // * + DIV = 0x33, // / + MOD = 0x34, // % + + AND = 0x40, // & + OR = 0x41, // | + XOR = 0x42, // ~ + NOT = 0x43, // ! (not) + + EQ = 0x50, // == + GT = 0x51, // > + GTEQ = 0x52, // >= + LT = 0x53, // < + LTEQ = 0x54, // <= + + JUMP16 = 0x60, // 跟 16 位索引 无条件 + JUMP32 = 0x61, // 跟 32 位索引 无条件 + + JUMP16_IF_TRUE = 0x62, // 跟 16 位索引 栈顶为真跳转 + JUMP32_IF_TRUE = 0x63, // 跟 32 位索引 栈顶为真跳转 + + JUMP16_IF_FALSE = 0x64, // 跟 16 位索引 栈顶为假跳转 + JUMP32_IF_FALSE = 0x65, // 跟 32 位索引 栈顶为假跳转 + + LOAD_LOCAL16 = 0x70, // 后跟 16 位索引 + LOAD_LOCAL32 = 0x71, // 后跟 32 位索引 + }; + + inline FString bytecode2string(Bytecode code) + { + const std::string_view &name = magic_enum::enum_name(code); + return FString(FStringView(name)); + } + + inline FString reverseCompile(const std::vector &src) + { + assert(src.size() >= 1); + + FString result; + + using enum Bytecode; + for (size_t i = 0; i < src.size();) + { + Bytecode code = Bytecode(src[i]); + switch (code) + { + case HALT: { + uint8_t quitCode = src[++i]; + result += FString(std::format("HALT {}", static_cast(quitCode))) + u8"\n"; + break; + } + case LOAD_CON8: { + uint8_t id = src[++i]; + result += FString(std::format("LOAD_CON8 {}", static_cast(id))) + u8"\n"; + break; + } + case LOAD_CON16: + case JUMP16: + case JUMP16_IF_TRUE: + case JUMP16_IF_FALSE: + case LOAD_LOCAL16: { + uint8_t high = src[++i]; + uint8_t low = src[++i]; + int32_t id = (high << 8) | low; + result += FString(std::format("{} {}", bytecode2string(code).toBasicString(), id)) + + u8"\n"; + break; + } + + case LOAD_CON32: + case JUMP32: + case JUMP32_IF_TRUE: + case JUMP32_IF_FALSE: + case LOAD_LOCAL32: { + uint32_t b0 = static_cast(src[++i]); + uint32_t b1 = static_cast(src[++i]); + uint32_t b2 = static_cast(src[++i]); + uint32_t b3 = static_cast(src[++i]); + + uint32_t id = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; + result += FString(std::format("{} {}", bytecode2string(code).toBasicString(), id)) + + u8"\n"; + break; + } + default: { + result += bytecode2string(code) + u8"\n"; + } + } + ++i; + } + return result; + } +}; // namespace Fig \ No newline at end of file diff --git a/src/Compiler/Compiler.cpp b/src/Compiler/Compiler.cpp new file mode 100644 index 0000000..c8d8d8d --- /dev/null +++ b/src/Compiler/Compiler.cpp @@ -0,0 +1,21 @@ +#include +#include +#include + +namespace Fig +{ + void Compiler::compile(Ast::Statement stmt) + { + using enum Ast::AstType; + using namespace Ast; + Ast::AstType type = stmt->getType(); + + switch (type) + { + case VarDefSt: { + auto vd = std::static_pointer_cast(stmt); + const FString name = vd->name; + } + } + } +}; // namespace Fig \ No newline at end of file diff --git a/src/Compiler/Compiler.hpp b/src/Compiler/Compiler.hpp new file mode 100644 index 0000000..3612283 --- /dev/null +++ b/src/Compiler/Compiler.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "Ast/astBase.hpp" +#include +#include +#include + +#include + +namespace Fig +{ + class Compiler + { + private: + std::vector source; + std::vector output; // std::vector + + std::vector constants; + public: + std::vector getOutput() const { return output; } + std::vector getConstantPool() const { return constants; } + + Compiler() {} + Compiler(std::vector _source) : source(std::move(_source)) {} + + void compile_expr(Ast::Expression); + + void compile(Ast::Statement); + + void CompileAll(); + }; +}; // namespace Fig \ No newline at end of file diff --git a/src/Core/fig_string.hpp b/src/Core/fig_string.hpp index 1d74a86..a676436 100644 --- a/src/Core/fig_string.hpp +++ b/src/Core/fig_string.hpp @@ -43,6 +43,10 @@ namespace Fig { return FString(toBasicString() + x.toBasicString()); } + FString operator+(const char8_t *c) + { + return FString(*this + std::u8string(c)); + } explicit FString(const std::u8string &str) { diff --git a/src/Context/context.hpp b/src/Evaluator/Context/context.hpp similarity index 70% rename from src/Context/context.hpp rename to src/Evaluator/Context/context.hpp index 92c0cdb..9709ac0 100644 --- a/src/Context/context.hpp +++ b/src/Evaluator/Context/context.hpp @@ -33,17 +33,13 @@ namespace Fig std::unordered_map functionNames; // implRegistry - std::unordered_map, TypeInfoHash> - implRegistry; + std::unordered_map, TypeInfoHash> implRegistry; public: ContextPtr parent; Context(const Context &) = default; - Context(const FString &name, ContextPtr p = nullptr) : - scopeName(name), parent(p) - { - } + Context(const FString &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {} void setParent(ContextPtr _parent) { parent = _parent; } @@ -55,37 +51,28 @@ namespace Fig { variables.insert(c.variables.begin(), c.variables.end()); functions.insert(c.functions.begin(), c.functions.end()); - functionNames.insert(c.functionNames.begin(), - c.functionNames.end()); + functionNames.insert(c.functionNames.begin(), c.functionNames.end()); implRegistry.insert(c.implRegistry.begin(), c.implRegistry.end()); // structTypeNames.insert(c.structTypeNames.begin(), // c.structTypeNames.end()); } - std::unordered_map getFunctions() const - { - return functions; - } + std::unordered_map getFunctions() const { return functions; } std::shared_ptr get(const FString &name) { auto it = variables.find(name); if (it != variables.end()) return it->second; if (parent) return parent->get(name); - throw RuntimeError(FString(std::format("Variable '{}' not defined", - name.toBasicString()))); + throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); } AccessModifier getAccessModifier(const FString &name) { if (variables.contains(name)) { return variables[name]->am; } - else if (parent != nullptr) - { - return parent->getAccessModifier(name); - } + else if (parent != nullptr) { return parent->getAccessModifier(name); } else { - throw RuntimeError(FString(std::format( - "Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); } } bool isVariableMutable(const FString &name) @@ -104,16 +91,14 @@ namespace Fig { if (!isVariableMutable(name)) { - throw RuntimeError(FString(std::format( - "Variable '{}' is immutable", name.toBasicString()))); + throw RuntimeError(FString(std::format("Variable '{}' is immutable", name.toBasicString()))); } variables[name]->value = value; } else if (parent != nullptr) { parent->set(name, value); } else { - throw RuntimeError(FString(std::format( - "Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); } } void _update(const FString &name, ObjectPtr value) @@ -122,8 +107,7 @@ namespace Fig else if (parent != nullptr) { parent->_update(name, value); } else { - throw RuntimeError(FString(std::format( - "Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); } } void def(const FString &name, @@ -133,14 +117,11 @@ namespace Fig { if (containsInThisScope(name)) { - throw RuntimeError(FString( - std::format("Variable '{}' already defined in this scope", - name.toBasicString()))); + throw RuntimeError( + FString(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); } - variables[name] = - std::make_shared(name, value, ti, am); - if (ti == ValueType::Function - and value->getTypeInfo() == ValueType::Function) + variables[name] = std::make_shared(name, value, ti, am); + if (ti == ValueType::Function and value->getTypeInfo() == ValueType::Function) { auto &fn = value->as(); functions[fn.id] = fn; @@ -152,19 +133,42 @@ namespace Fig // structTypeNames[st.id] = name; // } } + void + defReference(const FString &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr target) + { + if (containsInThisScope(name)) + { + throw RuntimeError( + FString(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); + } + variables[name] = std::make_shared( + name, + target->value, + ti, + am, + true, + target + ); + } std::optional getFunction(std::size_t id) { auto it = functions.find(id); if (it != functions.end()) { return it->second; } else if (parent) { return parent->getFunction(id); } - else { return std::nullopt; } + else + { + return std::nullopt; + } } std::optional getFunctionName(std::size_t id) { auto it = functionNames.find(id); if (it != functionNames.end()) { return it->second; } else if (parent) { return parent->getFunctionName(id); } - else { return std::nullopt; } + else + { + return std::nullopt; + } } // std::optional getStructName(std::size_t id) // { @@ -188,24 +192,15 @@ namespace Fig else if (parent != nullptr) { return parent->contains(name); } return false; } - bool containsInThisScope(const FString &name) const - { - return variables.contains(name); - } + bool containsInThisScope(const FString &name) const { return variables.contains(name); } - TypeInfo getTypeInfo(const FString &name) - { - return get(name)->declaredType; - } + TypeInfo getTypeInfo(const FString &name) { return get(name)->declaredType; } bool isInFunctionContext() { ContextPtr ctx = shared_from_this(); while (ctx) { - if (ctx->getScopeName().find(u8"getScopeName().find(u8"parent; } return false; @@ -215,8 +210,7 @@ namespace Fig ContextPtr ctx = shared_from_this(); while (ctx) { - if (ctx->getScopeName().find(u8"getScopeName().find(u8"getScopeName().find(u8"getScopeName().find(u8"hasImplRegisted(structType, interfaceType); } - std::optional - getImplRecord(const TypeInfo &structType, - const TypeInfo &interfaceType) const + std::optional getImplRecord(const TypeInfo &structType, const TypeInfo &interfaceType) const { auto it = implRegistry.find(structType); if (it != implRegistry.end()) @@ -257,9 +248,7 @@ namespace Fig return std::nullopt; } - void setImplRecord(const TypeInfo &structType, - const TypeInfo &interfaceType, - const ImplRecord &record) + void setImplRecord(const TypeInfo &structType, const TypeInfo &interfaceType, const ImplRecord &record) { auto &list = implRegistry[structType]; @@ -271,8 +260,7 @@ namespace Fig list.push_back(record); // order is the level } - bool hasMethodImplemented(const TypeInfo &structType, - const FString &functionName) const + bool hasMethodImplemented(const TypeInfo &structType, const FString &functionName) const { auto it = implRegistry.find(structType); if (it != implRegistry.end()) @@ -283,19 +271,16 @@ namespace Fig } } - return parent - && parent->hasMethodImplemented(structType, functionName); + return parent && parent->hasMethodImplemented(structType, functionName); } - bool hasDefaultImplementedMethod(const TypeInfo &structType, - const FString &functionName) const + bool hasDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) const { auto it = implRegistry.find(structType); if (it == implRegistry.end()) return false; std::vector implementedInterfaces; - for (auto &record : it->second) - implementedInterfaces.push_back(record.interfaceType); + for (auto &record : it->second) implementedInterfaces.push_back(record.interfaceType); for (auto &[_, slot] : variables) { @@ -303,25 +288,22 @@ namespace Fig InterfaceType &interface = slot->value->as(); - bool implemented = std::any_of( - implementedInterfaces.begin(), - implementedInterfaces.end(), - [&](const TypeInfo &ti) { return ti == interface.type; }); + bool implemented = std::any_of(implementedInterfaces.begin(), + implementedInterfaces.end(), + [&](const TypeInfo &ti) { return ti == interface.type; }); if (!implemented) continue; for (auto &method : interface.methods) { - if (method.name == functionName && method.hasDefaultBody()) - return true; + if (method.name == functionName && method.hasDefaultBody()) return true; } } return false; } - Function getDefaultImplementedMethod(const TypeInfo &structType, - const FString &functionName) + Function getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) { // O(N²) // SLOW @@ -335,8 +317,7 @@ namespace Fig if (it == implRegistry.end()) assert(false); std::vector implementedInterfaces; - for (auto &record : it->second) - implementedInterfaces.push_back(record.interfaceType); + for (auto &record : it->second) implementedInterfaces.push_back(record.interfaceType); for (auto &[_, slot] : variables) { @@ -344,10 +325,9 @@ namespace Fig InterfaceType &interface = slot->value->as(); - bool implemented = std::any_of( - implementedInterfaces.begin(), - implementedInterfaces.end(), - [&](const TypeInfo &ti) { return ti == interface.type; }); + bool implemented = std::any_of(implementedInterfaces.begin(), + implementedInterfaces.end(), + [&](const TypeInfo &ti) { return ti == interface.type; }); if (!implemented) continue; @@ -357,10 +337,8 @@ namespace Fig { if (!method.hasDefaultBody()) assert(false); - return Function(method.paras, - TypeInfo(method.returnType), - method.defaultBody, - shared_from_this()); + return Function( + method.paras, TypeInfo(method.returnType), method.defaultBody, shared_from_this()); } } } @@ -369,8 +347,7 @@ namespace Fig return Function(); // ignore warning } - const Function &getImplementedMethod(const TypeInfo &structType, - const FString &functionName) const + const Function &getImplementedMethod(const TypeInfo &structType, const FString &functionName) const { auto it = implRegistry.find(structType); if (it != implRegistry.end()) @@ -382,11 +359,10 @@ namespace Fig } } - if (parent) - return parent->getImplementedMethod(structType, functionName); + if (parent) return parent->getImplementedMethod(structType, functionName); assert(false); // not found - throw ""; // ignore warning + throw ""; // ignore warning } void printStackTrace(std::ostream &os = std::cerr, int indent = 0) const @@ -403,8 +379,7 @@ namespace Fig os << "[STACK TRACE]\n"; for (int i = static_cast(chain.size()) - 1; i >= 0; --i) { - os << " #" << (chain.size() - 1 - i) << " " - << chain[i]->scopeName.toBasicString() << "\n"; + os << " #" << (chain.size() - 1 - i) << " " << chain[i]->scopeName.toBasicString() << "\n"; } } }; diff --git a/src/Context/context_forward.hpp b/src/Evaluator/Context/context_forward.hpp similarity index 100% rename from src/Context/context_forward.hpp rename to src/Evaluator/Context/context_forward.hpp diff --git a/src/Value/LvObject.hpp b/src/Evaluator/Value/LvObject.hpp similarity index 100% rename from src/Value/LvObject.hpp rename to src/Evaluator/Value/LvObject.hpp diff --git a/src/Value/Type.hpp b/src/Evaluator/Value/Type.hpp similarity index 100% rename from src/Value/Type.hpp rename to src/Evaluator/Value/Type.hpp diff --git a/src/Value/VariableSlot.hpp b/src/Evaluator/Value/VariableSlot.hpp similarity index 100% rename from src/Value/VariableSlot.hpp rename to src/Evaluator/Value/VariableSlot.hpp diff --git a/src/Value/function.hpp b/src/Evaluator/Value/function.hpp similarity index 100% rename from src/Value/function.hpp rename to src/Evaluator/Value/function.hpp diff --git a/src/Value/interface.hpp b/src/Evaluator/Value/interface.hpp similarity index 100% rename from src/Value/interface.hpp rename to src/Evaluator/Value/interface.hpp diff --git a/src/Value/module.hpp b/src/Evaluator/Value/module.hpp similarity index 100% rename from src/Value/module.hpp rename to src/Evaluator/Value/module.hpp diff --git a/src/Value/structInstance.hpp b/src/Evaluator/Value/structInstance.hpp similarity index 100% rename from src/Value/structInstance.hpp rename to src/Evaluator/Value/structInstance.hpp diff --git a/src/Value/structType.hpp b/src/Evaluator/Value/structType.hpp similarity index 100% rename from src/Value/structType.hpp rename to src/Evaluator/Value/structType.hpp diff --git a/src/Value/value.cpp b/src/Evaluator/Value/value.cpp similarity index 100% rename from src/Value/value.cpp rename to src/Evaluator/Value/value.cpp diff --git a/src/Value/value.hpp b/src/Evaluator/Value/value.hpp similarity index 99% rename from src/Value/value.hpp rename to src/Evaluator/Value/value.hpp index 1613042..891eea3 100644 --- a/src/Value/value.hpp +++ b/src/Evaluator/Value/value.hpp @@ -557,10 +557,13 @@ namespace Fig auto rnv = rhs.getNumericValue(); if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Division by zero", "/", lhs, rhs))); - bool bothInt = lhs.is() && rhs.is(); + // bool bothInt = lhs.is() && rhs.is(); auto result = lhs.getNumericValue() / rnv; - if (bothInt && !isNumberExceededIntLimit(result)) - return Object(static_cast(result)); + // if (bothInt && !isNumberExceededIntLimit(result)) + // return Object(static_cast(result)); + + // int / int maybe decimals + // DO NOT convert it to INT return Object(result); } throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs))); diff --git a/src/Value/valueError.hpp b/src/Evaluator/Value/valueError.hpp similarity index 100% rename from src/Value/valueError.hpp rename to src/Evaluator/Value/valueError.hpp diff --git a/src/Evaluator/evaluator.cpp b/src/Evaluator/evaluator.cpp index 79d1e87..d4f9f3c 100644 --- a/src/Evaluator/evaluator.cpp +++ b/src/Evaluator/evaluator.cpp @@ -573,6 +573,12 @@ namespace Fig for (const auto &stmt : fnStruct.body->stmts) { StatementResult sr = evalStatement(stmt, newContext); + if (sr.isError()) + { + throw EvaluatorError(u8"UncaughtExceptionError", + std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), + stmt); + } if (!sr.isNormal()) { retVal = sr.result; @@ -683,20 +689,14 @@ namespace Fig } case AstType::InitExpr: { auto initExpr = std::dynamic_pointer_cast(exp); - if (!ctx->contains(initExpr->structName)) - { - throw EvaluatorError( - u8"StructNotFoundError", - std::format("Structure type '{}' not found", initExpr->structName.toBasicString()), - initExpr); - } - ObjectPtr structTypeVal = ctx->get(initExpr->structName)->value; + LvObject structeLv = evalLv(initExpr->structe, ctx); + ObjectPtr structTypeVal = structeLv.get(); + const FString &structName = structeLv.name(); if (!structTypeVal->is()) { - throw EvaluatorError( - u8"NotAStructTypeError", - std::format("'{}' is not a structure type", initExpr->structName.toBasicString()), - initExpr); + throw EvaluatorError(u8"NotAStructTypeError", + std::format("'{}' is not a structure type", structName.toBasicString()), + initExpr); } const StructType &structT = structTypeVal->as(); @@ -717,7 +717,8 @@ namespace Fig } // default value - if (argSize == 0) { + if (argSize == 0) + { if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function) { throw EvaluatorError( @@ -824,7 +825,7 @@ namespace Fig { throw EvaluatorError(u8"StructInitArgumentMismatchError", std::format("Structure '{}' expects {} to {} fields, but {} were provided", - initExpr->structName.toBasicString(), + structName.toBasicString(), minArgs, maxArgs, initExpr->args.size()), @@ -837,7 +838,7 @@ namespace Fig evaluatedArgs.push_back({argName, eval(argExpr, ctx)}); } ContextPtr instanceCtx = std::make_shared( - FString(std::format("", initExpr->structName.toBasicString())), ctx); + FString(std::format("", structName.toBasicString())), ctx); /* 3 ways of calling constructor .1 Person {"Fig", 1, "IDK"}; @@ -869,7 +870,7 @@ namespace Fig u8"StructFieldTypeMismatchError", std::format( "In structure '{}', field '{}' expects type '{}', but got type '{}'", - initExpr->structName.toBasicString(), + structName.toBasicString(), fieldName.toBasicString(), expectedType.toString().toBasicString(), prettyType(defaultVal).toBasicString()), @@ -886,7 +887,7 @@ namespace Fig throw EvaluatorError( u8"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", - initExpr->structName.toBasicString(), + structName.toBasicString(), fieldName.toBasicString(), expectedType.toString().toBasicString(), prettyType(argVal).toBasicString()), @@ -907,7 +908,7 @@ namespace Fig throw EvaluatorError(u8"StructFieldRedeclarationError", std::format("Field '{}' already initialized in structure '{}'", fieldName.toBasicString(), - initExpr->structName.toBasicString()), + structName.toBasicString()), initExpr); } if (i + 1 > got) @@ -925,7 +926,7 @@ namespace Fig u8"StructFieldTypeMismatchError", std::format( "In structure '{}', field '{}' expects type '{}', but got type '{}'", - initExpr->structName.toBasicString(), + structName.toBasicString(), fieldName.toBasicString(), expectedType.toString().toBasicString(), prettyType(defaultVal).toBasicString()), @@ -941,7 +942,7 @@ namespace Fig throw EvaluatorError( u8"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", - initExpr->structName.toBasicString(), + structName.toBasicString(), fieldName.toBasicString(), field.type.toString().toBasicString(), prettyType(argVal).toBasicString()), diff --git a/src/main.cpp b/src/Evaluator/main.cpp similarity index 100% rename from src/main.cpp rename to src/Evaluator/main.cpp diff --git a/src/Lexer/lexer.cpp b/src/Lexer/lexer.cpp index 4336661..8fe0cec 100644 --- a/src/Lexer/lexer.cpp +++ b/src/Lexer/lexer.cpp @@ -6,6 +6,10 @@ #include #include +#if 0 + #include // debug +#endif + namespace Fig { @@ -339,21 +343,31 @@ namespace Fig { FString numStr; bool hasPoint = false; - // 负号(减号) 直接交由 scanSymbol处理,在parser中被分类->与数字结合/变为操作数 + while (hasNext()) { UTF8Char ch = *it; - if (ch.isDigit() or ch == U'e') // . / e / - for scientific counting + + // 数字或e(原代码允许e在数字中间) + if (ch.isDigit() || ch == U'e') { numStr += ch.getString(); next(); } - else if (ch == U'-' and numStr.ends_with(U'-')) + // 负号:只有当后面还有字符且不是数字结尾时才处理 + else if (ch == U'-' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E'))) { numStr += ch.getString(); next(); } - else if (ch == U'.' and not hasPoint) + // 正号:同上 + else if (ch == U'+' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E'))) + { + numStr += ch.getString(); + next(); + } + // 小数点:只能有一个 + else if (ch == U'.' && !hasPoint) { hasPoint = true; numStr += ch.getString(); @@ -364,22 +378,96 @@ namespace Fig break; } } - // Numbers in Fig-lang - /* - 114514 - 1145.14 - 1.14e3 -> 1140 - 1.14e-3 -> 0.00114 - .3 -> 0.3 - */ - // checking legality - if ((*numStr.end()) == u'e') // e 后面必须跟整数表示科学计数 + + // 检查合法性 + if (numStr.empty()) { return IllegalTok; } + + // 检查以e结尾的情况 + if (numStr.ends_with(U'e')) { - error = SyntaxError(FString( - std::format("Ellegal number literal: {}", numStr.toBasicString())), - this->line, it.column()); + error = SyntaxError( + FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); return IllegalTok; } + + // 检查是否至少有一个数字 + bool hasDigit = false; + for (auto it = numStr.begin(); it != numStr.end(); ++it) + { + if (isdigit(*it)) + { + hasDigit = true; + break; + } + } + + if (!hasDigit) + { + error = SyntaxError( + FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); + return IllegalTok; + } + + // 检查科学计数法格式:e后面必须有数字 + size_t ePos = numStr.find(U'e'); + if (ePos != FString::npos) + { + // e不能在开头 + if (ePos == 0) + { + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column()); + return IllegalTok; + } + + // e后面必须有内容 + if (ePos + 1 >= numStr.length()) + { + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column()); + return IllegalTok; + } + + // 检查e后面的部分 + bool hasDigitAfterE = false; + for (size_t i = ePos + 1; i < numStr.length(); ++i) + { + UTF8Char c = std::u8string(1,numStr[i]); + if (c == U'+' || c == U'-') + { + // 符号只能紧跟在e后面 + if (i != ePos + 1) + { + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column()); + return IllegalTok; + } + continue; + } + + if (c.isDigit()) { hasDigitAfterE = true; } + else + { + // e后面只能有符号和数字 + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column()); + return IllegalTok; + } + } + + if (!hasDigitAfterE) + { + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column()); + return IllegalTok; + } + } + return Token(numStr, TokenType::LiteralNumber); } Token Lexer::scanSymbol() @@ -434,7 +522,7 @@ namespace Fig next(); return IllegalTok; } - + // std::cerr << Token(sym, symbol_map.at(sym)).toString().toBasicString() << '\n; next(); return Token(sym, symbol_map.at(sym)); } @@ -522,13 +610,13 @@ namespace Fig if (!hasNext()) { next(); - // return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column); + return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column); } c = it.peek(); if (c != U'/' and c != U'*') { next(); - // return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column); + return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column); } scanComments().setPos(last_line, last_column); return nextToken(); diff --git a/src/Module/Library/std/formater/formater.fig b/src/Module/Library/std/formater/formater.fig index d980345..ef4b321 100644 --- a/src/Module/Library/std/formater/formater.fig +++ b/src/Module/Library/std/formater/formater.fig @@ -7,17 +7,40 @@ import std.value; // `type` function and string_from + +struct FormatError +{ + public msg: String; +} + +impl Error for FormatError +{ + getErrorClass() + { + return "FormatError"; + } + getErrorMessage() + { + return getErrorClass() + ": " + msg; + } + toString() + { + return getErrorMessage(); + } +} + public func format(objects ...) -> Any { if objects.length() < 1 { - return null; + throw FormatError{"Require format string"}; } var fmt := objects[0]; - if value.type(fmt) != "String" + var fmtType := value.type(fmt); + if fmtType != "String" { - return null; + throw FormatError{"arg 0 (fmt) must be String type, got " + fmtType}; } var result := ""; @@ -33,7 +56,7 @@ public func format(objects ...) -> Any { if (i + 1 >= length) { - return null; + throw FormatError{"unclosed brace"}; } var nextChar = fmt[i + 1]; @@ -57,12 +80,12 @@ public func format(objects ...) -> Any if endIndex == -1 { - return null; + throw FormatError{"unclosed brace"}; } if argIndex >= objects.length() { - return null; + throw FormatError{"require enough format expression"}; } result += value.string_from(objects[argIndex]); @@ -79,7 +102,7 @@ public func format(objects ...) -> Any continue; } - return null; + throw FormatError{"invalid format syntax"}; } else { @@ -97,15 +120,16 @@ public func formatByListArgs(objects) -> Any { return null; } - if objects.length() < 1 +if objects.length() < 1 { - return null; + throw FormatError{"Require format string"}; } var fmt := objects[0]; - if value.type(fmt) != "String" + var fmtType := value.type(fmt); + if fmtType != "String" { - return null; + throw FormatError{"arg 0 (fmt) must be String type, got " + fmtType}; } var result := ""; @@ -121,7 +145,7 @@ public func formatByListArgs(objects) -> Any { if (i + 1 >= length) { - return null; + throw FormatError{"unclosed brace"}; } var nextChar = fmt[i + 1]; @@ -145,12 +169,12 @@ public func formatByListArgs(objects) -> Any if endIndex == -1 { - return null; + throw FormatError{"unclosed brace"}; } if argIndex >= objects.length() { - return null; + throw FormatError{"require enough format expression"}; } result += value.string_from(objects[argIndex]); @@ -167,7 +191,7 @@ public func formatByListArgs(objects) -> Any continue; } - return null; + throw FormatError{"invalid format syntax"}; } else { diff --git a/src/Module/Library/std/io/io.fig b/src/Module/Library/std/io/io.fig index f190865..79ea4b7 100644 --- a/src/Module/Library/std/io/io.fig +++ b/src/Module/Library/std/io/io.fig @@ -43,7 +43,8 @@ public func println(objects...) -> Int public func printf(objects...) -> Any { - __fstdout_print(formater.formatByListArgs(objects)); + var result := formater.formatByListArgs(objects); + __fstdout_print(result); } // inputs diff --git a/src/Parser/parser.cpp b/src/Parser/parser.cpp index 33a2343..55bf396 100644 --- a/src/Parser/parser.cpp +++ b/src/Parser/parser.cpp @@ -56,7 +56,15 @@ namespace Fig // {Ast::Operator::Dot, {40, 41}}, }; - Ast::VarDef Parser::__parseVarDef(bool isPublic) + const std::unordered_map Parser::unaryOpPrecedence = { + {Ast::Operator::Subtract, 150}, // - + {Ast::Operator::BitAnd, 150}, // & + {Ast::Operator::BitNot, 150}, // ~ + {Ast::Operator::Not, 150}, // ! + }; + + Ast::VarDef + Parser::__parseVarDef(bool isPublic) { // entry: current is keyword `var` or `const` bool isConst = (currentToken().getType() == TokenType::Const ? true : false); @@ -416,8 +424,7 @@ namespace Fig block)); continue; } - expect(TokenType::Semicolon); - next(); // consume `;` + expectSemicolon(); methods.push_back(Ast::InterfaceMethod( funcName, @@ -563,7 +570,7 @@ namespace Fig return makeAst(body, catches, finallyBlock); } - Ast::Statement Parser::__parseStatement() + Ast::Statement Parser::__parseStatement(bool allowExp) { Ast::Statement stmt; if (isThis(TokenType::EndOfFile)) { return makeAst(); } @@ -661,13 +668,21 @@ namespace Fig { stmt = __parseTry(); } - else + else if (allowExp) { // expression statement Ast::Expression exp = parseExpression(0); expectSemicolon(); stmt = makeAst(exp); } + else + { + throw SyntaxError( + u8"invalid syntax", + currentAAI.line, + currentAAI.column + ); + } return stmt; } Ast::BlockStatement Parser::__parseBlockStatement() @@ -700,7 +715,7 @@ namespace Fig } else { - condition = parseExpression(0); + condition = parseExpression(0, TokenType::LeftBrace); } // parenthesis is not required expect(TokenType::LeftBrace); // { @@ -723,7 +738,7 @@ namespace Fig } else { - elifCondition = parseExpression(0); + elifCondition = parseExpression(0, TokenType::LeftBrace); } expect(TokenType::LeftBrace); // { Ast::BlockStatement elifBody = __parseBlockStatement(); @@ -776,7 +791,9 @@ namespace Fig throwAddressableError(u8"Control flow statements cannot be used as for loop increment"); } - return __parseStatement(); + Ast::Expression exp = parseExpression(0, TokenType::LeftBrace); + // expectSemicolon(); we dont check the semicolon + return makeAst(exp); } Ast::For Parser::__parseFor() { @@ -788,14 +805,14 @@ namespace Fig next(); // consume `(` // support 3-part for loop // for init; condition; increment {} - Ast::Statement initStmt = __parseStatement(); // auto check `` + Ast::Statement initStmt = __parseStatement(false); // auto check `` Ast::Expression condition = parseExpression(0); expectSemicolon(); // auto consume `;` Ast::Statement incrementStmt = nullptr; if (!isThis(paren ? TokenType::RightParen : TokenType::LeftBrace)) // need parse increment? { - auto guard = disableSemicolon(); + // auto guard = disableSemicolon(); incrementStmt = __parseIncrementStatement(); } // after parse increment, semicolon check state restored if (paren) @@ -906,7 +923,7 @@ namespace Fig return makeAst(val); } - Ast::InitExpr Parser::__parseInitExpr(FString structName) + Ast::InitExpr Parser::__parseInitExpr(Ast::Expression structe) { // entry: current is `{` next(); // consume `{` @@ -917,7 +934,7 @@ namespace Fig .2 Person {name: "Fig", age: 1, sex: "IDK"}; // can be unordered .3 Person {name, age, sex}; */ - uint8_t mode; // 0=undetermined, 1=positional, 2=named, 3=shorthand + uint8_t mode = 0; // 0=undetermined, 1=positional, 2=named, 3=shorthand while (!isThis(TokenType::RightBrace)) { @@ -977,7 +994,7 @@ namespace Fig } expect(TokenType::RightBrace); next(); // consume `}` - return makeAst(structName, args, + return makeAst(structe, args, (mode == 1 ? Ast::InitExprAst::InitMode::Positional : (mode == 2 ? Ast::InitExprAst::InitMode::Named : Ast::InitExprAst::InitMode::Shorthand))); } @@ -1067,8 +1084,7 @@ namespace Fig throw SyntaxError(); } } - expect(TokenType::Semicolon); - next(); // consume `;` + expectSemicolon(); return makeAst(path); } @@ -1117,31 +1133,24 @@ namespace Fig { FString id = tok.getValue(); next(); - if (currentToken().getType() == TokenType::LeftBrace) - { - lhs = __parseInitExpr(id); // a_struct{init...} - } - else - { - lhs = __parseVarExpr(id); - } + lhs = __parseVarExpr(id); } else if (isTokenOp(tok) && isOpUnary((op = Ast::TokenToOp.at(tok.getType())))) { // prefix next(); - lhs = __parsePrefix(op, getRightBindingPower(op)); + lhs = makeAst(op, parseExpression(bp, stop, stop2)); } else { - throwAddressableError(FString(u8"Unexpected token in expression")); + throwAddressableError(FString(u8"Unexpected token in expression:") + tok.toString()); } // infix / (postfix) ? while (true) { tok = currentToken(); - if (tok.getType() == TokenType::Semicolon || tok == EOFTok) break; + if (tok.getType() == stop || tok.getType() == stop2|| tok == EOFTok) break; /* Postfix */ @@ -1151,6 +1160,12 @@ namespace Fig continue; } + if (tok.getType() == TokenType::LeftBrace) + { + lhs = __parseInitExpr(lhs); + continue; + } + // member access: a.b if (tok.getType() == TokenType::Dot) { @@ -1169,7 +1184,7 @@ namespace Fig if (tok.getType() == TokenType::LeftBracket) { next(); // consume '[' - auto indexExpr = parseExpression(0, TokenType::RightBracket); + auto indexExpr = parseExpression(0, TokenType::RightBracket, stop2); expect(TokenType::RightBracket); next(); // consume ']' @@ -1181,7 +1196,7 @@ namespace Fig if (tok.getType() == TokenType::Question) { next(); // consume ? - Ast::Expression trueExpr = parseExpression(0, TokenType::Colon); + Ast::Expression trueExpr = parseExpression(0, TokenType::Colon, stop2); expect(TokenType::Colon); next(); // consume : Ast::Expression falseExpr = parseExpression(0, TokenType::Semicolon, stop2); @@ -1196,7 +1211,7 @@ namespace Fig if (bp >= lbp) break; next(); // consume op - lhs = __parseInfix(lhs, op, getRightBindingPower(op)); + lhs = makeAst(lhs, op, parseExpression(bp, stop, stop2)); } return lhs; diff --git a/src/Parser/parser.hpp b/src/Parser/parser.hpp index 6e69317..dcb2800 100644 --- a/src/Parser/parser.hpp +++ b/src/Parser/parser.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Ast/astBase.hpp" #include #include #include @@ -38,15 +39,8 @@ namespace Fig bool original; public: - SemicolonDisabler(Parser *parser) : - p(parser), original(p->needSemicolon) - { - p->needSemicolon = false; - } - ~SemicolonDisabler() - { - p->needSemicolon = original; - } + SemicolonDisabler(Parser *parser) : p(parser), original(p->needSemicolon) { p->needSemicolon = false; } + ~SemicolonDisabler() { p->needSemicolon = original; } // disable copy and assign SemicolonDisabler(const SemicolonDisabler &) = delete; SemicolonDisabler &operator=(const SemicolonDisabler &) = delete; @@ -65,14 +59,8 @@ namespace Fig output.push_back(node); } - bool isTokenSymbol(Token tok) - { - return Lexer::symbol_map.contains(tok.getValue()); - } - bool isTokenOp(Token tok) - { - return Ast::TokenToOp.contains(tok.getType()); - } + bool isTokenSymbol(Token tok) { return Lexer::symbol_map.contains(tok.getValue()); } + bool isTokenOp(Token tok) { return Ast::TokenToOp.contains(tok.getType()); } bool isEOF() { if (tokenPruduced == 0) return false; @@ -82,21 +70,19 @@ namespace Fig public: using Precedence = uint32_t; static const std::unordered_map> opPrecedence; - Parser(const Lexer &_lexer) : - lexer(_lexer) - { - } + static const std::unordered_map unaryOpPrecedence; - AddressableError* getError() const - { - return error.get(); - } + Parser(const Lexer &_lexer) : lexer(_lexer) {} + + AddressableError *getError() const { return error.get(); } template - void throwAddressableError(FString msg, size_t line, size_t column, std::source_location loc = std::source_location::current()) + void throwAddressableError(FString msg, + size_t line, + size_t column, + std::source_location loc = std::source_location::current()) { - static_assert(std::is_base_of_v, - "_ErrT must derive from AddressableError"); + static_assert(std::is_base_of_v, "_ErrT must derive from AddressableError"); _ErrT spError(msg, line, column, loc); error = std::make_unique<_ErrT>(spError); throw spError; @@ -104,8 +90,7 @@ namespace Fig template void throwAddressableError(FString msg, std::source_location loc = std::source_location::current()) { - static_assert(std::is_base_of_v, - "_ErrT must derive from AddressableError"); + static_assert(std::is_base_of_v, "_ErrT must derive from AddressableError"); // line, column provide by `currentAAI` _ErrT spError(msg, currentAAI.line, currentAAI.column, loc); error = std::make_unique<_ErrT>(spError); @@ -115,22 +100,15 @@ namespace Fig template void throwUnaddressableError(FString msg, std::source_location loc = std::source_location::current()) { - static_assert(std::is_base_of_v, - "_ErrT must derive from AddressableError"); + static_assert(std::is_base_of_v, "_ErrT must derive from AddressableError"); _ErrT spError(msg, loc); error = std::make_unique<_ErrT>(spError); throw spError; } - void setCurrentAAI(Ast::AstAddressInfo _aai) - { - currentAAI = std::move(_aai); - } + void setCurrentAAI(Ast::AstAddressInfo _aai) { currentAAI = std::move(_aai); } - Ast::AstAddressInfo getCurrentAAI() const - { - return currentAAI; - } + Ast::AstAddressInfo getCurrentAAI() const { return currentAAI; } inline const Token &nextToken() { @@ -143,7 +121,8 @@ namespace Fig if (int64_t(currentTokenIndex - 1) < int64_t(0)) // 同下 next注释 { - throw std::runtime_error("Internal Error in Parser::rollbackToken, trying to rollback but it's already on the begin"); + throw std::runtime_error( + "Internal Error in Parser::rollbackToken, trying to rollback but it's already on the begin"); } currentTokenIndex--; } @@ -152,7 +131,8 @@ namespace Fig if (int64_t(currentTokenIndex) < (int64_t(tokenPruduced) - 1)) { /* - 必须两个都显示转换为int64_t.否则,负数时会超出范围,变成int64_t max, 并且 CTI也需要显示转换,否则转换完的pruduced又会被转回去,变为 int64_t max + 必须两个都显示转换为int64_t.否则,负数时会超出范围,变成int64_t max, 并且 + CTI也需要显示转换,否则转换完的pruduced又会被转回去,变为 int64_t max */ currentTokenIndex++; setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, .column = currentToken().column}); @@ -184,18 +164,11 @@ namespace Fig return tok; } - std::pair getBindingPower(Ast::Operator op) - { - return opPrecedence.at(op); - } - Precedence getLeftBindingPower(Ast::Operator op) - { - return getBindingPower(op).first; - } - Precedence getRightBindingPower(Ast::Operator op) - { - return getBindingPower(op).second; - } + const std::pair &getBindingPower(Ast::Operator op) const { return opPrecedence.at(op); } + Precedence getLeftBindingPower(Ast::Operator op) const { return getBindingPower(op).first; } + Precedence getRightBindingPower(Ast::Operator op) const { return getBindingPower(op).second; } + + const Precedence &getUnaryBp(Ast::Operator op) const { return unaryOpPrecedence.at(op); } // template // std::shared_ptr<_Tp> makeAst(Args &&...args) @@ -217,8 +190,9 @@ namespace Fig if (peekToken().getType() != type) { throwAddressableError(FString(std::format("Expected `{}`, but got `{}`", - magic_enum::enum_name(type), - magic_enum::enum_name(peekToken().getType()))), loc); + magic_enum::enum_name(type), + magic_enum::enum_name(peekToken().getType()))), + loc); } } @@ -226,9 +200,11 @@ namespace Fig { if (currentToken().getType() != type) { - throwAddressableError(FString(std::format("Expected `{}`, but got `{}`", - magic_enum::enum_name(type), - magic_enum::enum_name(currentToken().getType()))), loc); + throwAddressableError( + FString(std::format("Expected `{}`, but got `{}`", + magic_enum::enum_name(type), + magic_enum::enum_name(currentToken().getType()))), + loc); } } @@ -237,8 +213,9 @@ namespace Fig if (peekToken().getType() != type) { throwAddressableError(FString(std::format("Expected `{}`, but got `{}`", - expected.toBasicString(), - magic_enum::enum_name(peekToken().getType()))), loc); + expected.toBasicString(), + magic_enum::enum_name(peekToken().getType()))), + loc); } } @@ -246,16 +223,15 @@ namespace Fig { if (currentToken().getType() != type) { - throwAddressableError(FString(std::format("Expected `{}`, but got `{}`", - expected.toBasicString(), - magic_enum::enum_name(currentToken().getType()))), loc); + throwAddressableError( + FString(std::format("Expected `{}`, but got `{}`", + expected.toBasicString(), + magic_enum::enum_name(currentToken().getType()))), + loc); } } - [[nodiscard]] SemicolonDisabler disableSemicolon() - { - return SemicolonDisabler(this); - } + [[nodiscard]] SemicolonDisabler disableSemicolon() { return SemicolonDisabler(this); } void expectSemicolon() { @@ -287,14 +263,8 @@ namespace Fig next(); } - bool isNext(TokenType type) - { - return peekToken().getType() == type; - } - bool isThis(TokenType type) - { - return currentToken().getType() == type; - } + bool isNext(TokenType type) { return peekToken().getType() == type; } + bool isThis(TokenType type) { return currentToken().getType() == type; } static constexpr FString varDefTypeFollowed = u8"(Followed)"; @@ -313,28 +283,30 @@ namespace Fig Ast::VarExpr __parseVarExpr(FString); Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool) - Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool) - Ast::InterfaceDef __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool) - Ast::Implement __parseImplement(); // entry: current is `impl` + Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool) + Ast::InterfaceDef + __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool) + Ast::Implement __parseImplement(); // entry: current is `impl` - Ast::Throw __parseThrow(); // entry: current is `throw` - Ast::Try __parseTry(); // entry: current is `try` + Ast::Throw __parseThrow(); // entry: current is `throw` + Ast::Try __parseTry(); // entry: current is `try` Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence); Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence); Ast::Expression __parseCall(Ast::Expression); - - Ast::ListExpr __parseListExpr(); // entry: current is `[` - Ast::MapExpr __parseMapExpr(); // entry: current is `{` - Ast::InitExpr __parseInitExpr(FString); // entry: current is `{`, ahead is struct name. arg (struct name : FString) - Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` + Ast::ListExpr __parseListExpr(); // entry: current is `[` + Ast::MapExpr __parseMapExpr(); // entry: current is `{` + + Ast::InitExpr __parseInitExpr( + Ast::Expression); // entry: current is `{`, ahead is struct type exp. + Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function - Ast::Import __parseImport(); // entry: current is Token::Import - - Ast::Statement __parseStatement(); // entry: (idk) + Ast::Import __parseImport(); // entry: current is Token::Import + + Ast::Statement __parseStatement(bool = true); // entry: (idk) Ast::Expression parseExpression(Precedence, TokenType = TokenType::Semicolon, TokenType = TokenType::Semicolon); std::vector parseAll(); }; diff --git a/src/VMValue/VMValue.cpp b/src/VMValue/VMValue.cpp new file mode 100644 index 0000000..0694d84 --- /dev/null +++ b/src/VMValue/VMValue.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include + +namespace Fig +{ + FString Value::toString() const + { + if (static_cast(type) > static_cast(Double)) + { + return heap->toString(); + } + switch (type) + { + case Null: + return u8"null"; + case Bool: + return (b ? u8"true" : u8"false"); + case Int: + return FString(std::to_string(i)); + case Double: + return FString(std::to_string(d)); + + default: + assert(false); + } + } +}; \ No newline at end of file diff --git a/src/VMValue/VMValue.hpp b/src/VMValue/VMValue.hpp new file mode 100644 index 0000000..4be4873 --- /dev/null +++ b/src/VMValue/VMValue.hpp @@ -0,0 +1,91 @@ +#pragma once + +/* + value system for virtual machine + not Evaluator value +*/ + +#include + +#include + +namespace Fig +{ + struct HeapObject; + + struct Value + { + struct NullObject {}; + + enum _Type : uint8_t + { + Null = 0, + Bool, + Int, + Double, + + /* Complex types, alloc in heap*/ + String, + // Function, + // StructType, + // StructInstance, + // List, + // Map, + // Module, + // InterfaceType + } type; + + union + { + NullObject n; + bool b; + int64_t i; + double d; + + HeapObject *heap; + }; + + Value() + { + type = Null; + n = NullObject(); + } + + Value(bool _b) + { + type = Bool; + b = _b; + } + + Value(int64_t _i) + { + type = Int; + i = _i; + } + + Value(double _d) + { + type = Double; + d = _d; + } + + FString toString() const; + }; + + struct HeapObject + { + Value::_Type type; // > 3 + + virtual FString toString() const = 0; + }; + + struct String : HeapObject + { + FString value; + + virtual FString toString() const override + { + return value; + } + }; +}; \ No newline at end of file diff --git a/src/VirtualMachine/main.cpp b/src/VirtualMachine/main.cpp new file mode 100644 index 0000000..7eb5599 --- /dev/null +++ b/src/VirtualMachine/main.cpp @@ -0,0 +1,43 @@ +/* + + ███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ █████████ █████ █████ █████████ █████████ ██████████ +░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░█ +░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ ░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ + ░███ ░███████████ ░██████ ░███████ ░███ ░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ + ░███ ░███░░░░░███ ░███░░█ ░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ █████ ░███░░█ + ░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███ ░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ + █████ █████ █████ ██████████ █████ █████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ ██████████ + ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░ + + Copyright (C) 2020-2026 PuqiAR + +This software is licensed under the MIT License. See LICENSE for details. +*/ + + +// DO NOT USE CLANG-FORMAT FOR THIS FILE + +#include +#include + +int main() +{ + using namespace Fig; + + + std::vector src; + + { + using enum Bytecode; + src = { + 0x21, // LOAD_TRUE + 0x23, 0x7f, // LOAD_CON8 0x7f + 0x24, 0x12, 0x34, // LOAD_CON16 0x1234 + 0x25, 0x12, 0x34, 0x56, 0x78, // LOAD_CON32 0x12345678 + 0x63, 0x12, 0x34, 0x56, 0x78 // JUMP32_IF_TRUE + }; + + FString r = reverseCompile(src); + std::cout << r.toBasicString() << std::endl; + } +} \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index c905785..eb473ca 100644 --- a/xmake.lua +++ b/xmake.lua @@ -7,7 +7,6 @@ target("Fig") set_kind("binary") set_languages("c++23") - add_ldflags("-static", {force = true}) if is_plat("linux") then -- Linux: clang + libc++ @@ -27,15 +26,51 @@ target("Fig") end - add_files("src/main.cpp") + add_files("src/Evaluator/main.cpp") add_files("src/Core/warning.cpp") add_files("src/Evaluator/evaluator.cpp") + add_files("src/Evaluator/Value/value.cpp") add_files("src/Lexer/lexer.cpp") add_files("src/Parser/parser.cpp") - add_files("src/Value/value.cpp") add_includedirs("src") + add_includedirs("src/Evaluator") set_warnings("all") add_defines("__FCORE_COMPILE_TIME=\"" .. os.date("%Y-%m-%d %H:%M:%S") .. "\"") + +-- -- Bytecode VM target +-- target("Figc") +-- set_kind("binary") +-- set_languages("c++23") + +-- add_ldflags("-static", {force = true}) +-- if is_plat("linux") then +-- -- Linux: clang + libc++ +-- set_toolchains("clang") +-- add_cxxflags("-stdlib=libc++") +-- add_ldflags("-stdlib=libc++") +-- elseif is_plat("windows") then +-- -- 1. CI cross (Linux -> Windows) +-- -- 2. local dev (Windows + llvm-mingw) +-- set_toolchains("mingw") -- llvm-mingw +-- add_ldflags("-Wl,--stack,268435456") +-- -- set_toolchains("clang") +-- -- static lib +-- -- add_ldflags("-target x86_64-w64-mingw32", "-static") +-- -- add_cxxflags("-stdlib=libc++") +-- -- add_ldflags("-stdlib=libc++") +-- end + +-- add_includedirs("src/Evaluator") +-- add_files("src/Evaluator/Value/value.cpp") +-- add_files("src/VirtualMachine/main.cpp") +-- add_files("src/Core/warning.cpp") +-- add_files("src/Lexer/lexer.cpp") +-- add_files("src/Parser/parser.cpp") + +-- add_includedirs("src") +-- set_warnings("all") + +-- add_defines("__FCORE_COMPILE_TIME=\"" .. os.date("%Y-%m-%d %H:%M:%S") .. "\"")