Support var
This commit is contained in:
@@ -133,12 +133,13 @@ struct ExprStmt : public Stmt {
|
||||
};
|
||||
|
||||
struct VarDecl : public Stmt {
|
||||
std::string type_name;
|
||||
std::string type_name; // Can be empty if type inference is needed
|
||||
std::string name;
|
||||
ExprPtr initializer;
|
||||
bool infer_type; // true if type should be inferred from initializer
|
||||
|
||||
VarDecl(std::string type_name, std::string name, ExprPtr initializer = nullptr)
|
||||
: type_name(std::move(type_name)), name(std::move(name)), initializer(std::move(initializer)) {}
|
||||
VarDecl(std::string type_name, std::string name, ExprPtr initializer = nullptr, bool infer_type = false)
|
||||
: type_name(std::move(type_name)), name(std::move(name)), initializer(std::move(initializer)), infer_type(infer_type) {}
|
||||
};
|
||||
|
||||
struct BlockStmt : public Stmt {
|
||||
|
||||
@@ -367,7 +367,23 @@ void Interpreter::exec_var_decl(const VarDecl& stmt) {
|
||||
|
||||
if (stmt.initializer) {
|
||||
value = evaluate(*stmt.initializer);
|
||||
|
||||
// If type inference is needed, we use the value directly
|
||||
if (stmt.infer_type) {
|
||||
// Type is automatically inferred from the initializer value
|
||||
environment->define(stmt.name, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// If explicit type is provided, verify the value matches
|
||||
// (This is a simple check, could be more sophisticated)
|
||||
if (!stmt.type_name.empty()) {
|
||||
// Just use the value; type checking could be added here
|
||||
environment->define(stmt.name, value);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// No initializer, use default value based on type
|
||||
value = create_default_value(stmt.type_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,14 +94,9 @@ StmtPtr Parser::declaration() {
|
||||
if (match({TokenType::FUNC})) {
|
||||
return function_declaration();
|
||||
}
|
||||
if (check(TokenType::NUMBER) || check(TokenType::STRING) ||
|
||||
check(TokenType::BOOL) || check(TokenType::LIST) ||
|
||||
check(TokenType::MAP) || check(TokenType::IDENTIFIER)) {
|
||||
// Type name followed by identifier
|
||||
Token lookahead = tokens_[current_];
|
||||
if (current_ + 1 < tokens_.size() && tokens_[current_ + 1].type == TokenType::IDENTIFIER) {
|
||||
return var_declaration();
|
||||
}
|
||||
// Handle var keyword for variable declaration
|
||||
if (match({TokenType::VAR})) {
|
||||
return var_declaration();
|
||||
}
|
||||
|
||||
return statement();
|
||||
@@ -118,8 +113,10 @@ StmtPtr Parser::class_declaration() {
|
||||
if (check(TokenType::FUNC)) {
|
||||
advance();
|
||||
members.push_back(function_declaration());
|
||||
} else {
|
||||
} else if (match({TokenType::VAR})) {
|
||||
members.push_back(var_declaration());
|
||||
} else {
|
||||
throw error(peek(), "Expected 'var' or 'func' in class body.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,17 +158,35 @@ StmtPtr Parser::function_declaration() {
|
||||
}
|
||||
|
||||
StmtPtr Parser::var_declaration() {
|
||||
Token type_token = advance();
|
||||
std::string type_name = type_token.lexeme;
|
||||
Token name = consume(TokenType::IDENTIFIER, "Expected variable name.");
|
||||
// var keyword has already been consumed
|
||||
Token name = consume(TokenType::IDENTIFIER, "Expected variable name after 'var'.");
|
||||
|
||||
std::string type_name;
|
||||
bool infer_type = false;
|
||||
ExprPtr initializer = nullptr;
|
||||
if (match({TokenType::EQUAL})) {
|
||||
|
||||
// Check for explicit type annotation: var x : type
|
||||
if (match({TokenType::COLON})) {
|
||||
Token type_token = advance();
|
||||
type_name = type_token.lexeme;
|
||||
|
||||
// Optional initializer
|
||||
if (match({TokenType::EQUAL})) {
|
||||
initializer = expression();
|
||||
}
|
||||
} else {
|
||||
// No type annotation, must have initializer for type inference
|
||||
if (!match({TokenType::EQUAL})) {
|
||||
throw error(peek(), "Variable declaration without type annotation must have an initializer.");
|
||||
}
|
||||
initializer = expression();
|
||||
infer_type = true;
|
||||
type_name = ""; // Will be inferred at runtime
|
||||
}
|
||||
|
||||
consume(TokenType::SEMICOLON, "Expected ';' after variable declaration.");
|
||||
|
||||
return std::make_unique<VarDecl>(type_name, name.lexeme, std::move(initializer));
|
||||
return std::make_unique<VarDecl>(type_name, name.lexeme, std::move(initializer), infer_type);
|
||||
}
|
||||
|
||||
StmtPtr Parser::statement() {
|
||||
|
||||
Reference in New Issue
Block a user