Skip to content

Commit

Permalink
feat(parser): add new functions and enhance class extension syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Ze7111 committed Dec 8, 2024
1 parent 9dcc66e commit e70f2f8
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 19 deletions.
66 changes: 52 additions & 14 deletions source/helix.hlx
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,51 @@ fn something() requires <T> if foo::<int> in T {
T::bar();
}

fn helix_compiler(std::array::<std::string, N> args) -> i32 requires <N: std::size_t> {
let invoke: InvocationManager = InvocationManager(args, true);
let compile: CompilationUnit = CompilationUnit(invoke);
let diag_handle: PrettyDiagnosticHandler = PrettyDiagnosticHandler();

fn foo() -> i32? | $question::<i32> {
panic "this is a panic";
// breaks down to the following c++:
return PanicFrame(
"this is a panic",
"source/helix.hlx",
1, "foo"
);
}

fn abc() -> i32 {
let x = ["hello", "world"];

// fails to codegen correctly since the `as` requires a primary expr on the right
return x[0].length() as i32;
// the really annoying thing is the error message is not helpful at all, it just says
// "function `length` not found." which is not true. the reason is because the c++ codegen looks
// like this: `helix::std::as<i32>(x[0]).length()`, which is not correct and the reason it fails.
//
// couple of notes about helix:
// - the language is still in development and is not stable yet.
// - the language right now has a c++ backend, and the self-hosted compiler would initially also
// have a c++ backend. but that would be migrated to a llvm backend later on. (the c++ backend
// is just a temporary solution, since llvm is really hard to work with and the c++ backend is
// much easier to work with - for now)

// this is the fix: (looks bad but it's the only way to fix it right now)
return (x[0].length()) as i32;

// this is one of many little things that are very finicky in the language but it will be fixed
// with the self-hosted compiler.
//
// the current compiler is very limited in what it can do, but it's a start and does work for the
// most part, the self-hosted compiler will be able to do much more and be much more flexible.
}

fn helix_compiler(std::array::<std::string, N> args) -> i32
requires <N: std::size_t> {
let invoke = InvocationManager(args, true);
let compile = CompilationUnit(invoke);
let diag_handle = PrettyDiagnosticHandler();

// frontend processors
compile.add_frontend_processor(LexicalProcessor());
compile.add_frontend_processor(Mem::Heap::<LexicalProcessor>());
compile.add_frontend_processor(PreProcessor());
compile.add_frontend_processor(ASTProcessor());

Expand All @@ -56,40 +94,40 @@ fn helix_compiler(std::array::<std::string, N> args) -> i32 requires <N: std::si
// set diagnostics
compile.set_diagnostic_handler(diag_handle);

if (compile.execute() != InvocationManager::Success) {
if (compile.execute() != CompilationUnit::Success) {
switch (compile.exit_state) {
case InvocationManager::CompilerError:
case CompilationUnit::CompilerError:
log(
"compiler internal error: ",
diag_handle
.get<InvocationManager::CompilerError>()
.get<CompilationUnit::CompilerError>()
.format()
.to_string()
); break;

case InvocationManager::CodeError:
case CompilationUnit::CodeError:
log(
"user code error: ",
diag_handle
.get<InvocationManager::CodeError>()
.get<CompilationUnit::CodeError>()
.format()
.to_string()
); break;

case InvocationManager::UnrecoverableError:
case CompilationUnit::UnrecoverableError:
log(
"fatal error: ",
diag_handle
.get<InvocationManager::UnrecoverableError>()
.get<CompilationUnit::UnrecoverableError>()
.format()
.to_string()
); break;

case InvocationManager::SystemError:
case CompilationUnit::SystemError:
log(
"sys call error: ",
diag_handle
.get<InvocationManager::SystemError>()
.get<CompilationUnit::SystemError>()
.format()
.to_string()
); break;
Expand Down
5 changes: 5 additions & 0 deletions source/parser/preprocessor/source/macro_preprocessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@

/*
macro_def := 'macro' IDENTIFIER ( '(' IDENTIFIER ( ',' IDENTIFIER )* ')' )? '{' ANY* '}' ';'
FIXME : macro rules:
#... -> stringify
\... -> concat
\#... -> un-stringify
*/

struct MacroDef {
Expand Down
28 changes: 28 additions & 0 deletions test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <type_traits>
#include <concepts>

template<typename T>
concept SomeInterface = requires(T t) {
{ t.foo() } -> std::same_as<int>;
};


template <class T, typename...Es>
class AClass {};

template <class T, typename ...Es>
requires(std::is_class_v<Es> && ...)
class AClass<T, Es...> {

};

template <class T, typename ...Es>
requires (std::is_class_v<T> && (std::is_class_v<Es> && ...))
class AClass<T, Es...> // without extending an interface
{

};

int main() {

}
73 changes: 68 additions & 5 deletions test.hlx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
class Node {
pub let value: i32
pub let next: *Node = &null
pub let value: i32;
pub let next: *Node = &null;

// constructor for Node
fn Node(self, value: i32) {
self.value = value
self.value = value;
}
}

fn printReverseList(head: *Node) {
if head->next != &null:
printReverseList(head->next)
printReverseList(head->next);

print(f"{head->value} ")
print(f"{head->value} ");
}

fn pow(base: u64, exp: u64) -> u64 {
Expand Down Expand Up @@ -76,6 +76,69 @@ fn num_concat(number: &string) -> u64 {
return final_num;
}

class AClass
requires <T: class, ...Es> {
...
}

extend AClass::<T, Es...> with SomeInterface
requires <T: class, ...Es> if (traits::is_class_v::<Es> && ...) {
...
}

extend AClass::<T, Es...> // without extending an interface
requires <T: class, ...Es> if (traits::is_class_v::<T> && (traits::is_class_v::<Es> && ...)) {
...
}

// ------------------ simple example of requires specialization ------------------
class SomeOtherClass requires <T> {
...
}

extend SomeOtherClass::<T> with SomeInterface
requires <T> {
...
}

extend SomeOtherClass::<i32> { // without extending an interface and a specific type
...
}

// ------------------ even simpler example of requires specialization ------------------
class AnotherClass {
...
}

extend AnotherClass { // this directly adds everything defined in the extension into the class itself
...
}


interface JsonIfy {
fn to_json(self) -> string {};
}

class Book {
let val: i32;

fn Book(self, val: i32) {
self.val = val;
}

op as fn (self) -> string {
return "class: Book";
}
}

extend Book with JsonIfy {
fn to_json(self) -> &self {
return f"val: {*&self.val}";
}
}



// entry point
fn main() -> i32 {
let num = "123849771248217498127421874128412941";
Expand Down

0 comments on commit e70f2f8

Please sign in to comment.