windows specific changes
This commit is contained in:
parent
6e3379b5b8
commit
ec4b5afa9c
@ -3,6 +3,7 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <cctype>
|
||||
|
||||
inline std::vector<std::string> splitString(const std::string& input, const std::string& delimiter) {
|
||||
std::vector<std::string> tokens;
|
||||
@ -56,9 +57,9 @@ inline bool isHexDigit(char c) {
|
||||
return (std::isdigit(c) || (std::isxdigit(c) && std::islower(c)));
|
||||
}
|
||||
|
||||
inline u_long binaryStringToLong(const std::string& binaryString) {
|
||||
inline unsigned long long binaryStringToLong(const std::string& binaryString) {
|
||||
std::string binaryDigits = binaryString.substr(2); // Remove the '0b' prefix
|
||||
u_long result = 0;
|
||||
unsigned long long result = 0;
|
||||
for (char ch : binaryDigits) {
|
||||
result <<= 1;
|
||||
result += (ch - '0');
|
||||
|
||||
@ -22,7 +22,7 @@ enum TokenType{
|
||||
// Increment/decrement operators
|
||||
PLUS_PLUS, MINUS_MINUS,
|
||||
|
||||
IDENTIFIER, STRING, NUMBER, BOOL,
|
||||
IDENTIFIER, STRING, NUMBER, KW_BOOL,
|
||||
|
||||
AND, OR, TRUE, FALSE, IF, ELSE, FUNCTION, FOR,
|
||||
WHILE, DO, VAR, CLASS, EXTENDS, EXTENSION, SUPER, THIS, NONE, RETURN, BREAK, CONTINUE,
|
||||
@ -53,7 +53,7 @@ inline std::string enum_mapping[] = {"OPEN_PAREN", "CLOSE_PAREN", "OPEN_BRACE",
|
||||
|
||||
"PLUS_PLUS", "MINUS_MINUS",
|
||||
|
||||
"IDENTIFIER", "STRING", "NUMBER", "BOOL",
|
||||
"IDENTIFIER", "STRING", "NUMBER", "KW_BOOL",
|
||||
|
||||
"AND", "OR", "TRUE", "FALSE", "IF", "ELSE", "FUNCTION", "FOR",
|
||||
"WHILE", "DO", "VAR", "CLASS", "EXTENDS", "EXTENSION", "SUPER", "THIS", "NONE", "RETURN", "BREAK", "CONTINUE",
|
||||
|
||||
@ -74,6 +74,8 @@ private:
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::shared_ptr<Function>>> builtinExtensions; // keys: "string","array","dict","any"
|
||||
std::unordered_map<std::string, std::string> classParents; // child -> parent
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, Value>> classTemplates; // className -> template dict
|
||||
// Field initializers per class in source order (to evaluate across inheritance chain)
|
||||
std::unordered_map<std::string, std::vector<std::pair<std::string, std::shared_ptr<Expr>>>> classFieldInitializers; // className -> [(field, expr)]
|
||||
ErrorReporter* errorReporter;
|
||||
bool inThunkExecution = false;
|
||||
|
||||
@ -138,6 +140,12 @@ public:
|
||||
void setClassTemplate(const std::string& className, const std::unordered_map<std::string, Value>& tmpl);
|
||||
bool getClassTemplate(const std::string& className, std::unordered_map<std::string, Value>& out) const;
|
||||
std::unordered_map<std::string, Value> buildMergedTemplate(const std::string& className) const;
|
||||
// Field initializer APIs
|
||||
void setClassFieldInitializers(const std::string& className, const std::vector<std::pair<std::string, std::shared_ptr<Expr>>>& inits) { classFieldInitializers[className] = inits; }
|
||||
bool getClassFieldInitializers(const std::string& className, std::vector<std::pair<std::string, std::shared_ptr<Expr>>>& out) const {
|
||||
auto it = classFieldInitializers.find(className);
|
||||
if (it == classFieldInitializers.end()) return false; out = it->second; return true;
|
||||
}
|
||||
void addStdLibFunctions();
|
||||
// Module APIs
|
||||
Value importModule(const std::string& spec, int line, int column); // returns module dict
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
@ -4,9 +4,19 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <limits.h>
|
||||
#include <io.h>
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -15,19 +25,35 @@ void registerOsModule(Interpreter& interpreter) {
|
||||
// Process
|
||||
m.fn("getcwd", [](std::vector<Value>, int, int) -> Value {
|
||||
char buf[PATH_MAX];
|
||||
#if defined(_WIN32)
|
||||
if (_getcwd(buf, sizeof(buf))) return Value(std::string(buf));
|
||||
#else
|
||||
if (getcwd(buf, sizeof(buf))) return Value(std::string(buf));
|
||||
#endif
|
||||
return NONE_VALUE;
|
||||
});
|
||||
m.fn("chdir", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (a.size() != 1 || !a[0].isString()) return Value(false);
|
||||
#if defined(_WIN32)
|
||||
int rc = ::_chdir(a[0].asString().c_str());
|
||||
#else
|
||||
int rc = ::chdir(a[0].asString().c_str());
|
||||
#endif
|
||||
return Value(rc == 0);
|
||||
});
|
||||
m.fn("getpid", [](std::vector<Value>, int, int) -> Value {
|
||||
#if defined(_WIN32)
|
||||
return Value(static_cast<double>(GetCurrentProcessId()));
|
||||
#else
|
||||
return Value(static_cast<double>(getpid()));
|
||||
#endif
|
||||
});
|
||||
m.fn("getppid", [](std::vector<Value>, int, int) -> Value {
|
||||
#if defined(_WIN32)
|
||||
return NONE_VALUE; // not directly available; could use Toolhelp32Snapshot if needed
|
||||
#else
|
||||
return Value(static_cast<double>(getppid()));
|
||||
#endif
|
||||
});
|
||||
m.fn("name", [](std::vector<Value>, int, int) -> Value {
|
||||
#if defined(_WIN32)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "path_module.h"
|
||||
#include "Interpreter.h"
|
||||
#include <filesystem>
|
||||
#include <cctype>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -11,6 +12,17 @@ static std::string join_impl(const std::vector<Value>& parts){
|
||||
return p.generic_string();
|
||||
}
|
||||
|
||||
static bool isabs_impl(const std::string& s) {
|
||||
#if defined(_WIN32)
|
||||
if (s.size() >= 2 && (s[0] == '/' || s[0] == '\\')) return true; // root-relative on current drive
|
||||
if (s.rfind("\\\\", 0) == 0) return true; // UNC path
|
||||
if (s.size() >= 3 && std::isalpha(static_cast<unsigned char>(s[0])) && s[1] == ':' && (s[2] == '/' || s[2] == '\\')) return true; // C:\ or C:/
|
||||
return false;
|
||||
#else
|
||||
return !s.empty() && s[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
void registerPathModule(Interpreter& interpreter) {
|
||||
interpreter.registerModule("path", [](Interpreter::ModuleBuilder& m) {
|
||||
m.fn("join", [](std::vector<Value> a, int, int) -> Value {
|
||||
@ -37,7 +49,7 @@ void registerPathModule(Interpreter& interpreter) {
|
||||
});
|
||||
m.fn("isabs", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (a.size()!=1 || !a[0].isString()) return Value(false);
|
||||
return Value(fs::path(a[0].asString()).is_absolute());
|
||||
return Value(isabs_impl(a[0].asString()));
|
||||
});
|
||||
m.fn("relpath", [](std::vector<Value> a, int, int) -> Value {
|
||||
if (a.size()<1 || a.size()>2 || !a[0].isString() || (a.size()==2 && !a[1].isString())) return NONE_VALUE;
|
||||
|
||||
@ -2,7 +2,11 @@
|
||||
#include "Interpreter.h"
|
||||
#include "Environment.h"
|
||||
#include "Lexer.h" // for Token and IDENTIFIER
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@ -111,8 +111,23 @@ Value Evaluator::visitBinaryExpr(const std::shared_ptr<BinaryExpr>& expression)
|
||||
case PLUS: return left + right;
|
||||
case MINUS: return left - right;
|
||||
case STAR: return left * right;
|
||||
case SLASH: return left / right;
|
||||
case PERCENT: return left % right;
|
||||
case SLASH: {
|
||||
if (right.isNumber() && right.asNumber() == 0.0) {
|
||||
// Report precise site for division by zero
|
||||
interpreter->reportError(expression->oper.line, expression->oper.column,
|
||||
"Runtime Error", "Division by zero", "/");
|
||||
throw std::runtime_error("Division by zero");
|
||||
}
|
||||
return left / right;
|
||||
}
|
||||
case PERCENT: {
|
||||
if (right.isNumber() && right.asNumber() == 0.0) {
|
||||
interpreter->reportError(expression->oper.line, expression->oper.column,
|
||||
"Runtime Error", "Modulo by zero", "%");
|
||||
throw std::runtime_error("Modulo by zero");
|
||||
}
|
||||
return left % right;
|
||||
}
|
||||
case BIN_AND: return left & right;
|
||||
case BIN_OR: return left | right;
|
||||
case BIN_XOR: return left ^ right;
|
||||
|
||||
@ -391,11 +391,11 @@ void Executor::visitClassStmt(const std::shared_ptr<ClassStmt>& statement, Execu
|
||||
} else {
|
||||
interpreter->registerClass(statement->name.lexeme, "");
|
||||
}
|
||||
// Predefine fields as none, keep initializers mapped
|
||||
std::unordered_map<std::string, std::shared_ptr<Expr>> fieldInitializers;
|
||||
// Predefine fields as none, capture this class's field initializers, and register them for inheritance evaluation
|
||||
std::vector<std::pair<std::string, std::shared_ptr<Expr>>> fieldInitializers;
|
||||
for (const auto& f : statement->fields) {
|
||||
classDict[f.name.lexeme] = NONE_VALUE;
|
||||
fieldInitializers[f.name.lexeme] = f.initializer;
|
||||
fieldInitializers.emplace_back(f.name.lexeme, f.initializer);
|
||||
}
|
||||
|
||||
// Attach methods as functions closed over a prototype env
|
||||
@ -411,6 +411,8 @@ void Executor::visitClassStmt(const std::shared_ptr<ClassStmt>& statement, Execu
|
||||
|
||||
// Save template to interpreter so instances can include inherited fields/methods
|
||||
interpreter->setClassTemplate(statement->name.lexeme, classDict);
|
||||
// Register field initializers for this class
|
||||
interpreter->setClassFieldInitializers(statement->name.lexeme, fieldInitializers);
|
||||
|
||||
// Define a constructor function Name(...) that builds an instance dict
|
||||
auto ctorName = statement->name.lexeme;
|
||||
@ -422,17 +424,31 @@ void Executor::visitClassStmt(const std::shared_ptr<ClassStmt>& statement, Execu
|
||||
for (const auto& kv : tmpl) dictRef[kv.first] = kv.second;
|
||||
// Tag instance with class name for extension lookup
|
||||
dictRef["__class"] = Value(className);
|
||||
// Evaluate field initializers with this bound
|
||||
if (!fieldInitializers.empty()) {
|
||||
// Evaluate field initializers across inheritance chain (parent-to-child order)
|
||||
{
|
||||
// Build chain from base to current
|
||||
std::vector<std::string> chain;
|
||||
std::string cur = className;
|
||||
while (!cur.empty()) { chain.push_back(cur); cur = runtime->getParentClass(cur); }
|
||||
std::reverse(chain.begin(), chain.end());
|
||||
auto saved = runtime->getEnvironment();
|
||||
auto env = std::make_shared<Environment>(saved);
|
||||
env->setErrorReporter(nullptr);
|
||||
env->define("this", instance);
|
||||
runtime->setEnvironment(env);
|
||||
for (const auto& kv : fieldInitializers) {
|
||||
if (kv.second) {
|
||||
Value v = runtime->evaluate(kv.second);
|
||||
dictRef[kv.first] = v;
|
||||
for (const auto& cls : chain) {
|
||||
std::vector<std::pair<std::string, std::shared_ptr<Expr>>> inits;
|
||||
if (runtime->getClassFieldInitializers(cls, inits)) {
|
||||
for (const auto& kv : inits) {
|
||||
const std::string& fieldName = kv.first;
|
||||
const auto& expr = kv.second;
|
||||
if (expr) {
|
||||
Value v = runtime->evaluate(expr);
|
||||
dictRef[fieldName] = v;
|
||||
// Expose field names as locals for subsequent initializers
|
||||
env->define(fieldName, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runtime->setEnvironment(saved);
|
||||
@ -445,6 +461,10 @@ void Executor::visitClassStmt(const std::shared_ptr<ClassStmt>& statement, Execu
|
||||
std::shared_ptr<Environment> newEnv = std::make_shared<Environment>(fn->closure);
|
||||
newEnv->setErrorReporter(nullptr);
|
||||
newEnv->define("this", instance);
|
||||
// Seed current class for proper super resolution within init
|
||||
if (fn && !fn->ownerClass.empty()) {
|
||||
newEnv->define("__currentClass", Value(fn->ownerClass));
|
||||
}
|
||||
// Bind params
|
||||
size_t n = std::min(fn->params.size(), args.size());
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
||||
@ -8,7 +8,11 @@
|
||||
#include "Expression.h"
|
||||
#include "Parser.h"
|
||||
#include <filesystem>
|
||||
#if defined(_WIN32)
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user