Skip to content

Commit

Permalink
Goodbye my old friend
Browse files Browse the repository at this point in the history
  • Loading branch information
mauro-balades committed Apr 16, 2024
1 parent 68c3d50 commit 8cebaa2
Show file tree
Hide file tree
Showing 32 changed files with 392 additions and 148 deletions.
2 changes: 1 addition & 1 deletion runtime/libs/exceptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct OurExceptionType_t {
*/
struct SnowballExceptionInstance_t {
// TODO: check if theres actually a vtable?
//void* _vtable;
void* _vtable;
char* message;

int length;
Expand Down
4 changes: 2 additions & 2 deletions src/ast/cache/FunctionCache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ void Functions::performInheritance(types::DefinedType* ty, types::DefinedType* p
name = childUUID + "." + name;
for (auto fn : functions) { setFunction(name, fn.function, fn.state); }
}
for (auto f : parent->getFields()) {
ty->addField(f);
for (auto f = parent->getFields().rbegin(); f != parent->getFields().rend(); f++) {
ty->addField(*f, true);
}
ty->hasVtable = parent->hasVtable;
return;
Expand Down
1 change: 1 addition & 0 deletions src/ast/syntax/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum Attributes {
EXPORT,
OVERRIDE,
FIRST_ARG_IS_SELF,
EXPLICIT,
UNSAFE_FUNC_NOT_BODY,
UNSAFE, // also used for blocks

Expand Down
5 changes: 4 additions & 1 deletion src/ast/types/DefinedType.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ DefinedType::ClassField::ClassField(
, initializedValue(initializedValue)
, isMutable(isMutable) { }
Syntax::Statement::DefinedTypeDef* DefinedType::getAST() const { return ast; }
void DefinedType::addField(ClassField* f) { fields.emplace_back(f); }
void DefinedType::addField(ClassField* f, bool toStart) {
if (toStart) fields.insert(fields.begin(), f);
else fields.emplace_back(f);
}
bool DefinedType::is(DefinedType* ty) const {
auto otherArgs = ty->getGenerics();
bool genericSizeEqual = otherArgs.size() == generics.size();
Expand Down
5 changes: 4 additions & 1 deletion src/ast/types/DefinedType.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ class DefinedType : public AcceptorExtend<DefinedType, BaseType> {
/// @note It does not include the parent fields!
auto& getFields() const { return fields; }
/// @brief Append a new field (ClassField) to the list
void addField(ClassField* f);
void addField(ClassField* f, bool toStart = false);
/// @brief Set the fields for the class
/// @note This should not be used unless you know what you are doing
void setFields(std::vector<ClassField*> f) { fields = f; }
/// @c Type::toRef() for information about this function.
/// @note It essentially does the same thing except it adds
/// generics if needed
Expand Down
2 changes: 1 addition & 1 deletion src/ast/types/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class InterfaceType : public BaseType {
std::string getMangledName() const override;
/// @return A list containing all the fields declared for the interface
/// @note It does not include the parent fields!
auto getFields() const { return fields; }
auto& getFields() const { return fields; }
/// @brief Add a new field to the interface
void addField(Member* f) { fields.emplace_back(f); }
/// @c Type::toRef() for information about this function.
Expand Down
3 changes: 2 additions & 1 deletion src/builder/llvm/DIHelpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ llvm::DIType* LLVMBuilder::getDIType(types::Type* ty) {
dbgInfo->line,
layout.getTypeAllocSizeInBits(getLLVMType(t->type)),
0,
structLayout->getElementOffsetInBits(fieldIndex),
fieldIndex < llvmType->getStructNumElements() ?
structLayout->getElementOffsetInBits(fieldIndex) : 0,
llvm::DINode::FlagZero,
getDIType(t->type)
);
Expand Down
1 change: 1 addition & 0 deletions src/builder/llvm/LLVMBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ LLVMBuilder::LLVMBuilder(
llvm::initializeHardwareLoopsPass(registry);
llvm::initializeReplaceWithVeclibLegacyPass(registry);
llvm::initializeTypePromotionLegacyPass(registry);

newContext();
module = newModule();
}
Expand Down
9 changes: 9 additions & 0 deletions src/builder/llvm/buildIntrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ bool LLVMBuilder::buildIntrinsic(ir::Call* call) {
} else if (name == "sn.debugbreak") {
assert(args.size() == 0);
builder->CreateIntrinsic(llvm::Intrinsic::debugtrap, {}, {});
} else if (name == "sn.discriminant") {
assert(args.size() == 1);
auto val = expr(args[0].get());
if (val->getType()->isPointerTy()) {
this->value = builder->CreateStructGEP(getLLVMType(args[0]->getType()), val, 0); // the analyser should have ensured this is an enum
this->value = builder->CreateLoad(builder->getInt32Ty(), this->value);
} else {
this->value = builder->CreateExtractValue(val, 0);
}
} else Syntax::E<BUG>(call, FMT("unknown intrinsic: %s", name.c_str()));
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/errors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void NiceError::print_error(bool asTail) const {
Logger::elog(FMT(" %s%4i%s │ %s", BBLK, cb_dbg_info->line - 1, BLK, cb_dbg_info->line_before.c_str()));
// highlight line where the error is
// e.g. hello<String>(1, 2, 3)
// ~~~~~
// ~~~~~
// converted to
// [white]hello[gray]<string>(1, 2, 3)
std::string line_str = "";
Expand Down
3 changes: 3 additions & 0 deletions src/lexer/lexer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,9 @@ void Lexer::tokenize() {
prefix += "l";
EAT_CHAR(1);
}
if (!prefix.empty() && mode == FLOAT) {
lexer_error(Error::SYNTAX_ERROR, "invalid float number suffix", prefix.size());
}
tk.value = prefix + tk.value;
tokens.emplace_back(tk);
if (isRange) { // we add '..' if it's a range expr (1..5)
Expand Down
7 changes: 6 additions & 1 deletion src/parser/parseClass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ return Attributes::INVALID;
auto var = parseConstant();
var->setPrivacy(Syntax::Statement::Privacy::fromInt(!inPrivateScope));
if (var->getValue() == nullptr) {
createError<SYNTAX_ERROR>("expected a value for constant declaration!");
createError<SYNTAX_ERROR>("expected a value for constant declaration!", {
.note = "Static constants must have a value initialized because they don't "
"have a constructor to initialize them.",
.help = "To fix this error, you can either remove the 'static' keyword or "
"initialize the constant with a value."
});
}
cls->addVariable(var);
assert_tok<TokenType::SYM_SEMI_COLLON>("a ';'");
Expand Down
4 changes: 3 additions & 1 deletion src/parser/parseFunction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ FunctionDef* Parser::parseFunction(bool isConstructor, bool isOperator, bool isL
return Attributes::NO_MANGLE;
} else if (attr == "export") {
return Attributes::EXPORT;
} else if (attr == "explicit") {
return Attributes::EXPLICIT;
} else if (attr == "bench") {
return Attributes::BENCH;
} else if (attr == "__internal__") {
Expand Down Expand Up @@ -394,7 +396,7 @@ return Attributes::INVALID;
if (is<TokenType::KWORD_SUPER>()) {
hasSuperArgs = true;
if (!m_current_class->getParent()) {
createError<SYNTAX_ERROR>("Cant call super on a class that doesn't extend "
createError<SYNTAX_ERROR>("Cant call super on a class that doesnt extend "
"from another class!");
}
next();
Expand Down
14 changes: 12 additions & 2 deletions src/services/ImportService.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,24 @@ ImportService::getImportPath(const std::string package, std::vector<std::string>
if (!exists) {
if (fs::is_directory(fullPath)) {
auto configFile = fullPath / "sn.toml";
if (!fs::exists(configFile)) {
auto libPath = fullPath / "lib.sn";
if (fs::exists(libPath)) {
return {libPath, fullPath, ""};
}
return {"", "", "Package doesnt have a sn.toml file!"};
}

auto config = toml::parse_file(configFile.string());
auto entry = config["package"]["main"].value_or<std::string>("<invalid>");
if (entry == "<invalid>") {
return {"", "", "Package doesn't have a main entry defined!"};
return {"", "", "Package doesnt have a main entry defined!"};
}
auto finalPath = fullPath / entry;
if (fullPath.stem().empty()) fullPath = fullPath.parent_path();
assert(access(finalPath.c_str(), F_OK) != -1);
if (access(finalPath.c_str(), F_OK) == -1) {
return {"", "", "Package main entry doesnt exist!"};
}
return {finalPath, fullPath, ""};
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/visitors/TransformContext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ TransformContext::TransformContext(
auto coreMod = std::make_shared<ir::Module>("Std", imports->CORE_UUID);
auto coreModItem = std::make_shared<transform::Item>(coreMod);
addItem("Std", coreModItem);
std::vector<std::string> coreBuiltins = {"Sized", "Numeric", "Callable"};
std::vector<std::string> coreBuiltins = {"Sized", "Numeric", "Callable", "EnumType"};
for (const auto& builtin : coreBuiltins) {
const auto baseUuid = imports->CORE_UUID + builtin;
auto transformedType = new types::InterfaceType(builtin, baseUuid, coreMod, {});
Expand Down
2 changes: 2 additions & 0 deletions src/visitors/transform/utils/executeGenericTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ void Transformer::executeGenericTests(Expression::WhereClause* clause, types::Ty
if ((utils::is<types::IntType>(generic) || utils::is<types::FloatType>(generic))
&& (interface->getUUID() == (ctx->imports->CORE_UUID + "std.ToString:0"))) { // note: Make sure to always match the UUID
found = true;
} else if (utils::is<types::EnumType>(generic) && interface->is(ctx->getBuiltinTypeImpl("EnumType"))) {
found = true;
}
}
if (!found) {
Expand Down
2 changes: 1 addition & 1 deletion src/visitors/transform/utils/getBestFittingFunction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Transformer::getBestFittingFunction(
}
argsEqual = arguments.at(i)->is(type);
//if (type->isMutable() && !arguments.at(i)->isMutable()) argsEqual = false;
if (!argsEqual) {
if (!argsEqual && !foundFunction.first.function->hasAttribute(Attributes::EXPLICIT)) {
if (auto castType = canCast(arguments.at(i), type); castType != CastType::NoCast) {
argsEqual = true;
argsNeedCasting = true;
Expand Down
2 changes: 1 addition & 1 deletion src/visitors/transform/utils/getFromIndex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Transformer::getFromIndex(DBGSourceInfo* dbgInfo, Expression::Index* index, bool
std::shared_ptr<ir::Value> indexValue = nullptr;
if (!isStatic) {
#define FIND_FIELD(field_type) \
auto fields = ty->getFields(); \
auto& fields = ((decltype(ty))ty->getModule()->typeInformation[ty->getId()].get())->getFields(); \
bool fieldFound = false; \
auto fieldValue = std::find_if(fields.begin(), fields.end(), [&](field_type* f) { \
bool e = f->name == name; \
Expand Down
24 changes: 12 additions & 12 deletions src/visitors/transform/utils/initializePerModuleMacros.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ namespace Syntax {

void Transformer::initializePerModuleMacros() {
auto pkgMacro = N<Macro>(
"pkg",
std::vector<std::tuple<std::string, Macro::ArguementType, Node*>> {
{"e", Macro::ArguementType::EXPRESSION, nullptr}
},
nullptr
);
"pkg",
std::vector<std::tuple<std::string, Macro::ArguementType, Node*>> {
{"e", Macro::ArguementType::EXPRESSION, nullptr}
},
nullptr
);
auto pkgInstance = new transform::MacroInstance(pkgMacro, ctx->module);
auto pkgMacroItem = std::make_shared<transform::Item>(pkgInstance);
ctx->addItem("pkg", pkgMacroItem);
auto zeroInitMacro = N<Macro>(
"zero_initialized",
std::vector<std::tuple<std::string, Macro::ArguementType, Node*>> {
{"type", Macro::ArguementType::TYPE, nullptr}
},
nullptr
);
"zero_initialized",
std::vector<std::tuple<std::string, Macro::ArguementType, Node*>> {
{"type", Macro::ArguementType::TYPE, nullptr}
},
nullptr
);
auto zeroInitInstance = new transform::MacroInstance(zeroInitMacro, ctx->module);
auto zeroInitMacroItem = std::make_shared<transform::Item>(zeroInitInstance);
ctx->addItem("zero_initialized", zeroInitMacroItem);
Expand Down
6 changes: 3 additions & 3 deletions src/visitors/transform/visits/Expression/ConstantValue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ SN_TRANSFORMER_VISIT(Expression::ConstantValue) {
}
snowball_int_t n = 0;
if (utils::startsWith(str, "0x") || utils::startsWith(str, "0X")) {
n = std::stoll(str, nullptr, 16);
n = std::stoull(str, nullptr, 16);
} else if (utils::startsWith(str, "0b") || utils::startsWith(str, "0B")) {
n = std::stoul(str.substr(2, (size_t)(str.size() - 2)), nullptr, 2);
n = std::stoull(str.substr(2, (size_t)(str.size() - 2)), nullptr, 2);
} else if (utils::startsWith(str, "0o") || utils::startsWith(str, "0O")) {
n = std::stoul(str.substr(2, (size_t)(str.size() - 2)), nullptr, 8);
n = std::stoull(str.substr(2, (size_t)(str.size() - 2)), nullptr, 8);
} else {
// TODO: big numbers!
n = std::stoull(str);
Expand Down
55 changes: 55 additions & 0 deletions stdlib/cli/arg.sn
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import std::opt::{Option, none, some}

/**
* @brief A class representing a command-line argument.
*
* This class represents a command-line argument, which typically serves as input parameters for a command-line program.
* An argument can have attributes such as a name, description, required flag, and default value. Command-line arguments
* are used to specify input values or configurations when executing a program from the command line.
*/
public class Arg {
/// @brief The name of the argument.
let mut name: String;
/// @brief The description of the argument.
let mut description: Option<String>;
/// @brief Flag indicating whether the argument is required.
let mut required: bool;
/// @brief The default value of the argument.
let mut default_val: Option<String>;
/**
* @brief Constructs an Arg object with the specified parameters.
* @param[in] name The name of the argument.
* @param[in] description The description of the argument.
* @param[in] required Flag indicating whether the argument is required.
* @param[in] default_val The default value of the argument.
*/
public: Arg(name: String, description: String = "", required: bool = false) {
self.name = name;
if description.empty() { self.description = none<?String>(); }
else { self.description = some(description); }
self.required = required;
self.default_val = none<?String>();
}
/// Sets the name of the argument.
@inline mut func name(n: String) Self
{ self.name = n; return self; }
/// Sets the description of the argument.
@inline mut func description(d: String) Self
{ self.description = some(d); return self; }
/// Sets the required flag of the argument.
@inline mut func required(r: bool) Self
{ self.required = r; return self; }
/// Sets the default value of the argument.
@inline mut func default_val(d: String) Self
{ self.default_val = some(d); return self; }
/// Returns the name of the argument.
@inline func name() String { return self.name; }
/// Returns the description of the argument.
@inline func description() Option<String> { return self.description; }
/// Returns the required flag of the argument.
@inline func required() bool { return self.required; }
/// Returns the default value of the argument.
@inline func default_val() Option<String> { return self.default_val; }
/// Overloads the equality operator for the Arg class.
operator func ==(other: Arg) bool { return self.name == other.name; }
}
Loading

0 comments on commit 8cebaa2

Please sign in to comment.