hades-lang
所属分类:编程语言基础
开发工具:kotlin
文件大小:0KB
下载次数:0
上传日期:2023-11-13 16:18:38
上 传 者:
sh-1993
说明: 一种系统编程语言
(A systems programming language)
文件列表:
.editorconfig (20, 2023-11-21)
.idea/ (0, 2023-11-21)
.idea/codeStyles/ (0, 2023-11-21)
.idea/codeStyles/Project.xml (381, 2023-11-21)
.idea/codeStyles/codeStyleConfig.xml (144, 2023-11-21)
.idea/runConfigurations/ (0, 2023-11-21)
.idea/runConfigurations/HadesTestSuite.xml (859, 2023-11-21)
bdwgc/ (0, 2023-11-21)
bindings/ (0, 2023-11-21)
bindings/cjson.hds (1821, 2023-11-21)
bindings/gl.hds (19302, 2023-11-21)
bindings/glfw.hds (690, 2023-11-21)
build.gradle.kts (0, 2023-11-21)
build_all_distributions.sh (152, 2023-11-21)
build_libhdc.sh (259, 2023-11-21)
cJSON/ (0, 2023-11-21)
default.properties (66, 2023-11-21)
design/ (0, 2023-11-21)
design/ref.md (2757, 2023-11-21)
distribution_smoke_test.py (1044, 2023-11-21)
docs/ (0, 2023-11-21)
docs/index.md (592, 2023-11-21)
examples/ (0, 2023-11-21)
examples/gtk-hello-world/ (0, 2023-11-21)
examples/gtk-hello-world/Makefile (700, 2023-11-21)
examples/gtk-hello-world/gtk.hds (3981, 2023-11-21)
examples/gtk-hello-world/main.hds (1249, 2023-11-21)
examples/gui-app/ (0, 2023-11-21)
... ...
# Hades
[![Build](https://github.com/dhruvrajvanshi/hades-lang/actions/workflows/ci.yml/badge.svg)](https://github.com/dhruvrajvanshi/hades-lang/actions/workflows/ci.yml)
[![codecov](https://codecov.io/github/dhruvrajvanshi/hades-lang/branch/master/graph/badge.svg?token=Y3E81BS5OK)](https://codecov.io/github/dhruvrajvanshi/hades-lang)
A systems level programming language that compiles to LLVM
- [x] Easy interop with C
- [x] Structs
- [x] Generic types
- [x] Extension Methods
- [x] Closures
- Pure stack allocated closures (i.e. can't be returned from functions and stored in structs right now)
- Once we have proper destructor semantics, I'll implement heap allocated closures that get cleaned up according to their lifetime.
- [ ] Named function arguments
- [x] Traits
- [x] Use after move checking:
- Unlike Rust, move is explicit. Types can be made Move only by implementing a builtin NoCopy trait.
- This is like C++ except the compiler prevents you from using a reference after moving it.
- [ ] Rust style destructors using `Drop` trait (Not implemented)
- [x] Associated trait types
- [x] Algebraic data types (enums)
- [x] Windows support
- Editor integration
- Syntax hilighting
- [x] VSCode
- [x] Intellij
- [ ] Error highlighting
- [ ] Autocompletion
- [x] Debugger support:
- Very basic support for gdb and lldb debug symbols is supported. This allows stepping through code using VS code. No local variables are shown yet.
## Intro
Hades is a language that I as an application developer would want to use.
Things that it focuses on
- Ergonomics: Should not be too low level like Rust or C++.
- Interop: Should be easy to bridge to other languages (currently, writing bindings for C is relatively easy).
- Performance: Should still be able to control memory layout to write high performance/allocation free code when required.
- Library oriented: I want the generic system to be like Swift. i.e. by default, generics should be compiled down to regular parameters so that libraries can be separately compiled. As an optimization, the compiler should monomorphize the generic calls if required. Hades doesn't currently work like this. As of now, everything is monomorphized, and there's no way to compile libraries.
- Modern: Algebraic data types, first class closures,
- IDE features: This is a stretch goal, but I'd like to have an LSP implementation.
## Getting started
### Prerequisites
* Python 3 needs to be installed.
* OpenJDK 11 or later needs to be installed (https://adoptopenjdk.net/ has Java builds for windows).
On Linux, you can usually find `openjdk-11` builds in your package manager (`apt/dnf install openjdk-11`)
### Installation
You can install the latest version of hades using this command
```sh
curl https://raw.githubusercontent.com/dhruvrajvanshi/hades-lang/master/install.py | python3 -
```
On windows, you can run this in prowershell
```powershell
# make sure you've installed python 3 beforehand
(Invoke-webrequest -URI "https://raw.githubusercontent.com/dhruvrajvanshi/hades-lang/master/install.py").Content | python -
```
This will install the latest build from the master branch in ~/.hades/versions/latest/hades (%APPDATA%\hades on windows).
Now, restarting your terminal should put `hades` command on your path.
You can install specific releases by appending `---version ` to the commands, where `` can be replaced with any
[tag version](https://github.com/dhruvrajvanshi/hades-lang/tags) from the releases page. `latest` tag is automatically built when something is pushed to master.
## Development
The current compiler lives under the hadesboot directory (self hosting is a long term goal).
Running the test suite is done using gradle.
```
./gradlew test
```
Building the compiler
```
./gradlew install
```
This installs the compiler executable in hadesboot/target directory. Check out examples directory makefiles
to see how a typical hades binary is built.
## Editor support
Basic syntax hilighting is supported
### IntelliJ
1. Git checkout this repo.
2. Go to `File > Settings > Editor > TextMate bundles`
3. Add a new bundle from directory `ide/vscode-hades`.
You should now get basic syntax hilighting for .hds files.
### VS Code
Plugin isn't published yet. It's in `ide/vscode-hades` Figure it out.
Instructions to come in the future.
## Hello world
```scala
extern def puts(*u8): Void = puts // by default, programs are linked with libc. This means you can declare pre-existing C functions as extern
def main(): Void {
puts(b"Hello world");
}
```
Local variables
```scala
def main(): Void {
val x: *Byte = b"Hello world"; // the type annotation can be omitted
c.puts(x);
}
```
## Some bindings for a C library
![gtk bindings screenshot](images/screenshot.png)
## A bigger example
```scala
// A struct has a packed layout like C
struct Pair[A, B] {
val first: A;
val second: B;
}
def main(): Void {
if true {
val pair = Pair(1, b"text"); // Type arguments to Pair are inferred
print_pair_second(pair); // function arguments are passed as value (a copy of pair is sent to print_pair
val pair_ptr = &pair; // you can take address of local variables and pass them as pointers
pair.print_second(); // this is an extension function call
val mut_pair_ptr = &mut pair // taking a mutable pointer
puts(mut_pair_ptr.second) // calling dot on a pointer dereferences it
val second_field_ptr = &pair.second // we can get a field offset using &stuctval.field
mut_pair_ptr.second = b"value" // dereferencing dot operator works for assignments as well
}
}
def print_pair_second[T](pair: Pair[T, *Byte]): Void {
c.puts(pair.second);
}
// extension methods can be defined for any type including types from
// different libraries
// some/nested_module.hds
extension PairExtensions[T] for Pair[T, *Byte] {
// `*this` means this extension takes its receiver by pointer
// Use `*mut this` to treat receiver pointer as mutable
// and `this` to take it as value
def print_second(*this): Void {
c.puts(this.second); // Unlike this.second on a pointer to a struct is equivalent to this->second in C
}
}
// in another file
// Importing a module brings extensions exported by that module
// into scope. This isn't transitive i.e. extensions imported by
// nested_module would not be available here. You have to separately
// import those.
import some.nested_module as nested_module;
def main(): Void {
val x = Pair(true, b"x");
// because extension method is declared as *this,
// we have to take pointer to x to pass it to the method.
(&x).print_second();
}
```
## Traits
Hades has a trait system similar to Rust. Traits allow us to define operations on generic
type parameters. This has the advantage of better error messages than C++ while still
being more powerful than simpler systems like Java interfaces.
```scala
trait Printable[Self] {
def print(self: Self): Void;
}
// Interfaces are implemented outside the type declaration
// this means you can make builtin types implement new interfaces
implementation Printable[Bool] {
def print(self: Bool): Void {
if *this {
c.puts(b"true");
} else {
c.puts(b"false");
}
}
}
// Unlike C++, the body of this function can be checked independently
// of call sites. No type errors on expanded templates :)
// The where clause is a requirement on type T and a caller can only pass things that are Printable
def print[T](value: T): Void where Printable[T] {
Printable[T].print(value);
}
def main(): Void {
print(true);
print(10); // type error: Printable[Int] not found
}
```
Implementations can have type parameters and where clauses, making it possible to implement traits
for generic types based on other traits.
```scala
struct Box[T] {
val value: T;
}
// this declaration says that for all type Ts, Box[T] is printable if T is printable.
// This makes it more powerful that Java/C# interfaces where it's not possible
// to have an interface for Equality/Hashing and have generic containers conform
// to them based on their type parameter.
// Equality and Hashing, Stringification is baked into all objects in Java to get around this problem
// but it doesn't solve it for custom interfaces.
implementation[T] Printable[Box[T]] where Printable[T] {
def print(self: Box[T]): Void {
print(b"Box("); // implementation Box[*Byte] is omitted for berevity
print(self);
print(b")");
}
}
def f() {
print(Box(true)); // works
print(Box(b"hello")); // works
print(Box(10)); // Type error because we haven't provided a Printable[Int] implementation
}
```
Although traits directly can't define extension methods yet, (i.e. you have to call `Trait[Type].method(value)`, instead of `value.method()`,
extension definitions can have where clauses, allowing you to wrap trait functions as extension methods.
```scala
extension StringifiableExtensions[T] for T where Stringifiable[T] {
def to_string(this): *Byte { return Stringifiable[T].print(this); }
}
def f[T](value: T): Void where Stringifiable[T] {
// now you can call to_string as a method
value.to_string();
}
```
Directly defining methods inside traits is being considered.
## Enum types
Enum types (also known as algebraic data types) allow you to represent types that can be one of a finite set
of cases.
```scala
enum Optional[T] {
Some(value: T);
None;
}
/// This compiles down to the equivalent of this (the names are mangled so
/// this isn't valid hades source code, but they are equivalent
/// struct Optional[T] {
/// val tag: u8
/// val payload: Union[Optional.Some[T], Optional.None]
/// }
/// struct Optional.Some[T] {
/// val 0: T
/// }
/// const Optional.Some.tag : u8 = 0
/// struct Optional.None[T] {}
/// const Optional.None.tag : u8 = 1
/// Optional.Some[u32](1) ~ Optional[u32](Optional.Some.tag, Optional.Some(1))
/// Optional.None[u32] ~ Optional[u32](Optional.None.tag)
def main(): Void {
// Enum types can be pattern matched on.
// The cases are checked at compile time. If you
// decide to add a new case, that will have to
// be handled in existing match statements.
val ten = match Optional.Some(10) {
// notice the use of `val` keyword to disambiguate enum case names
// from parameter binding patterns.
// this is different from rust, where patterns can be qualified,
// haskell, where data Cases have to start with uppercase (I think?)
// and swift where constructor cases are prefixed with a `.` to distinguish
// from bound patterns.
// An explicit `val` keyword has an added advantage of being easily searchable.
Some(val value) -> value,
None -> 0
};
val zero = match Optional.None[Int] {
Some(val value) -> value,
None -> 0
};
}
```
Enums don't have to carry extra data.
```
// The underlying representation of an enum tag is
// u8 (8 bit unsigned integer)
enum Token {
Identifier
Number
String
}
```
This will be similar to a C style enum (except more type safe because you can't assign itegers to them)
## Closures
Hades supports a limited form of closures that are allocated on the stack. This means that
they can't be returned from functions or stored in structs.
Once proper destruction and move semantics are implemented, this restriction can be lifted by
heap allocated closures.
```scala
def main(): Void {
puts(apply(true, |value| if (value) b"true" else b"false")); // prints "true"
// closures can have a block body
// prints "Done"
puts(apply(true, |value| {
if value {
return b"Done";
} else {
return b"Not done";
}
});
}
def apply[T, U](arg: T, fn: (T) -> U): U {
return fn(arg);
}
```
## Misc
Check the suite directory for a few contrived examples used as an automated test suite.
There's a gtk-hello-world which is a good representative program.
Proper documentation coming in the future.
近期下载者:
相关文件:
收藏者: