Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dc5e669
refactor: replace `enumerable` implementation with `enum` type, adjus…
VxTi Mar 15, 2026
0163eb0
Partially added support for generic overload function lookup and codegen
VxTi Mar 16, 2026
cd8adef
Rename function arguments
VxTi Mar 16, 2026
87921f1
Add support for generic function overloads and improve handling of LL…
VxTi Mar 16, 2026
9325a5c
refactor: replace `combine` with `join` in `SourceFragment` for clari…
VxTi Mar 16, 2026
340cb36
refactor: restructure function definition declarations and improve ha…
VxTi Mar 16, 2026
7172c23
refactor: rename `function_definition` to `function_declaration` and …
VxTi Mar 16, 2026
a963b5f
refactor: improve function name handling and streamline generic overl…
VxTi Mar 16, 2026
13253b2
refactor: add `set_type` and `set_visibility` methods, enable variabl…
VxTi Mar 16, 2026
7e41c41
refactor: update const qualifiers for variable definitions and improv…
VxTi Mar 16, 2026
a976680
refactor: move `resolve_forward_references` from `AstFunctionCall` to…
VxTi Mar 16, 2026
d7daa73
refactor: add `resolve_generics_in_body` for recursive generic resolu…
VxTi Mar 16, 2026
3f06386
Resolved generic resolution for functions
VxTi Mar 16, 2026
0a00eba
Added validation for string comparisons
VxTi Mar 16, 2026
e94c446
Resolve and enhance generic type handling for structures and functions
VxTi Mar 16, 2026
ea4883f
Resolve and improve generic type substitution for function calls and …
VxTi Mar 16, 2026
4991539
Enhance generic function handling by adding LLVM function attributes …
VxTi Mar 16, 2026
40e6d33
Add generic support for function calls and improve type resolution
VxTi Mar 16, 2026
7669ad0
Resolve function-like variable lookup, resolved segfault by incorrect…
VxTi Mar 16, 2026
60fcbbf
Added guard clause for edge case to prevent out of bounds access
VxTi Mar 16, 2026
8950525
Removed redundant comment
VxTi Mar 16, 2026
90f41f7
Added additional conditions for function call check to prevent incorr…
VxTi Mar 16, 2026
5f57a42
Add additional test for generic type resolution
VxTi Mar 16, 2026
95bed91
Add handling for unresolved generic parameters in type inference and …
VxTi Mar 16, 2026
076d060
Refactor code generation and generic handling logic
VxTi Mar 16, 2026
0b8966b
Improve handling of generic functions in declarations and calls
VxTi Mar 16, 2026
5d989d3
Added function call visitor to ensure function calls instantiate gene…
VxTi Mar 17, 2026
47d332d
Enhance generic function handling by adding support for retrieving ge…
VxTi Mar 18, 2026
f0e6eb8
Renamed `parsing_context` to `symbol_table`
VxTi Mar 25, 2026
001d75d
Refactor AST structure to use AstBranch for file representation and u…
VxTi Mar 25, 2026
56b954f
Enhance generic function support by adding a visitor for concrete typ…
VxTi Mar 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions example.sr
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
import System::{
io::print,
io::print
};

enum Test {
First: 123,
Second: 456,
Third: 789
type Array<T> = {
elements: T[];
count: i32;
// at: (i32) -> T;
};

fn arrayOf<T>(elements: T[], count: i32): Array<T> {
return Array<T>::{
elements,
count,
// at: (index: i32): T -> elements[index]
};
}

fn main(): i32 {
type Callback = () -> void;

const k: Test = Test::First;
fn makeCb(): Callback {
const names = arrayOf<string>(["Toyota", "Honda", "Ford", "Toyota"], 4);

io::print("k[0] = %d", k);
return (): void -> io::print("\x1b[32mDriving the car: %s", names.elements[1]);
}

fn main(): i32 {
makeCb()();

return 0;
}
60 changes: 53 additions & 7 deletions packages/compiler/include/ast/ast.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once
#include "parsing_context.h"

#include "symbol_table.h"
#include "ast/nodes/blocks.h"

#include <map>
#include <memory>
Expand All @@ -19,11 +21,55 @@ namespace stride::ast
{
using FilePath = std::string;

// A branch, representing a file in the AST
class AstBranch
{
std::shared_ptr<SourceFile> _source_file;
std::unique_ptr<AstBlock> _node;

public:
explicit AstBranch(
std::shared_ptr<SourceFile> source_file,
std::unique_ptr<AstBlock> node
) :
_source_file(std::move(source_file)),
_node(std::move(node)) {}

[[nodiscard]]
const std::string& get_file_content() const
{
return this->_source_file->source;
}

[[nodiscard]]
const std::string& get_file_path() const
{
return this->_source_file->path;
}

[[nodiscard]]
SourceFile* get_source_file() const
{
return this->_source_file.get();
}

[[nodiscard]]
AstBlock* get_node() const
{
return this->_node.get();
}

std::unique_ptr<AstBlock> release_node()
{
return std::move(this->_node);
}
};

class Ast
{
std::map<FilePath, std::unique_ptr<AstBlock>> _files{};
std::map<std::string, std::unique_ptr<AstBranch>> _branches;

static std::pair<FilePath, std::unique_ptr<AstBlock>> parse_file(const FilePath& path);
static std::pair<FilePath, std::unique_ptr<AstBranch>> parse_file(const FilePath& path);

public:
static std::unique_ptr<Ast> parse_files(
Expand All @@ -34,19 +80,19 @@ namespace stride::ast

void print() const;

const std::map<FilePath, std::unique_ptr<AstBlock>>& get_files()
const std::map<std::string, std::unique_ptr<AstBranch>>& get_branches()
{
return this->_files;
return this->_branches;
}
};

std::unique_ptr<IAstNode> parse_next_statement(
const std::shared_ptr<ParsingContext>& context,
const std::shared_ptr<SymbolTable>& context,
TokenSet& set
);

std::unique_ptr<AstBlock> parse_sequential(
const std::shared_ptr<ParsingContext>& context,
const std::shared_ptr<SymbolTable>& context,
TokenSet& set
);
}
144 changes: 144 additions & 0 deletions packages/compiler/include/ast/definitions/definitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#pragma once
#include "ast/symbols.h"


namespace stride::ast::definition
{
class FunctionDefinition;

enum class SymbolType
{
CLASS,
VARIABLE,
ENUM,
ENUM_MEMBER,
STRUCT,
STRUCT_MEMBER
};

class IDefinition
{
Symbol _symbol;
VisibilityModifier _visibility;

public:
explicit IDefinition(
Symbol symbol,
const VisibilityModifier modifier
) :
_symbol(std::move(symbol)),
_visibility(modifier) {}

virtual ~IDefinition() = default;

[[nodiscard]]
std::string get_internal_symbol_name() const
{
return this->_symbol.internal_name;
}

[[nodiscard]]
Symbol get_symbol() const
{
return this->_symbol;
}

[[nodiscard]]
VisibilityModifier get_visibility() const
{
return this->_visibility;
}

[[nodiscard]]
virtual std::unique_ptr<IDefinition> clone() const = 0;

void set_visibility(const VisibilityModifier visibility)
{
this->_visibility = visibility;
}
};

class TypeDefinition
: public IDefinition
{
std::unique_ptr<IAstType> _type;
GenericParameterList _generics;

public:
explicit TypeDefinition(
Symbol type_name_symbol,
std::unique_ptr<IAstType> type,
GenericParameterList generics,
const VisibilityModifier visibility
) :
IDefinition(std::move(type_name_symbol), visibility),
_type(std::move(type)),
_generics(std::move(generics)) {}

[[nodiscard]]
IAstType* get_type() const
{
return this->_type.get();
}

[[nodiscard]]
GenericParameterList get_generics_parameters() const
{
return this->_generics;
}

[[nodiscard]]
bool is_generic() const
{
return !this->_generics.empty();
}

[[nodiscard]]
std::unique_ptr<IDefinition> clone() const override
{
return std::make_unique<TypeDefinition>(
get_symbol(),
_type->clone_ty(),
get_generics_parameters(),
get_visibility());
}
};

class FieldDefinition : public IDefinition
{
std::unique_ptr<IAstType> _type;

/// Can be either a variable or a field in a struct/class
public:
explicit FieldDefinition(
const Symbol& symbol,
std::unique_ptr<IAstType> type,
const VisibilityModifier visibility
) :
IDefinition(symbol, visibility),
_type(std::move(type)) {}

[[nodiscard]]
IAstType* get_type() const
{
return this->_type.get();
}

[[nodiscard]]
std::string get_field_name() const
{
return this->get_symbol().name;
}

[[nodiscard]]
std::unique_ptr<IDefinition> clone() const override
{
return std::make_unique<FieldDefinition>(get_symbol(), _type->clone_ty(), get_visibility());
}

void set_type(std::unique_ptr<IAstType> type)
{
this->_type = std::move(type);
}
};
} // namespace stride::ast::definition
107 changes: 107 additions & 0 deletions packages/compiler/include/ast/definitions/function_definition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once

#include "ast/definitions/definitions.h"
#include "ast/nodes/function_declaration.h"

#include <memory>
#include <vector>

namespace stride::ast::definition
{
struct GenericFunctionOverload
{
std::vector<std::unique_ptr<IAstType>> generic_overload_types;
mutable llvm::Function* function;
mutable std::unique_ptr<AstFunctionDeclaration> node;
};

class FunctionDefinition
: public IDefinition
{
std::unique_ptr<AstFunctionType> _function_type;
std::vector<GenericFunctionOverload> _generic_overloads{};
int _flags;

llvm::Function* _llvm_function = nullptr;

public:
explicit FunctionDefinition(
std::unique_ptr<AstFunctionType> function_type,
const Symbol& symbol,
const VisibilityModifier visibility,
const int flags
) :
IDefinition(symbol, visibility),
_function_type(std::move(function_type)),
_flags(flags) {}

[[nodiscard]]
AstFunctionType* get_type() const
{
return this->_function_type.get();
}

[[nodiscard]]
std::string get_function_name() const
{
return this->get_symbol().name;
}

[[nodiscard]]
int get_flags() const
{
return this->_flags;
}

[[nodiscard]]
bool is_variadic() const
{
return (this->_flags & SRFLAG_FN_TYPE_VARIADIC) != 0;
}

void add_generic_instantiation(GenericTypeList generic_overload_types);

[[nodiscard]]
const std::vector<GenericFunctionOverload>& get_generic_overloads() const
{
return this->_generic_overloads;
}

[[nodiscard]]
bool has_generic_instantiation(const GenericTypeList& generic_types) const;

llvm::Function* get_generic_overload_llvm_function(const GenericTypeList& generic_types) const;

~FunctionDefinition() override = default;

bool matches_type_signature(const std::string& name, const AstFunctionType* signature) const;

void set_llvm_function(llvm::Function* function)
{
this->_llvm_function = function;
}

[[nodiscard]]
llvm::Function* get_llvm_function() const
{
return this->_llvm_function;
}

[[nodiscard]]
bool matches_parameter_signature(
const std::string& internal_function_name,
const std::vector<std::unique_ptr<IAstType>>& other_parameter_types,
size_t generic_argument_count
) const;

[[nodiscard]]
std::unique_ptr<IDefinition> clone() const override
{
return std::make_unique<FunctionDefinition>(
_function_type->clone_as<AstFunctionType>(),
get_symbol(),
get_visibility(),
_flags);
}
};
}
Loading
Loading