From 8408983bc2694ced6544ee52ee056e5541ec65c0 Mon Sep 17 00:00:00 2001 From: Andrew Segavac Date: Wed, 16 Jun 2021 12:02:02 -0600 Subject: [PATCH] updated readme --- README.md | 75 +++++++++++++++++++++++++++++++++++++++---------------- notes.txt | 26 ------------------- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 1e42a66..443908b 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,56 @@ -# Boring Lang Proposal - -**NOTE: This repo is a work in progress as I learn compiler writing, I may abandon this.** -**NOTE: The rust code in the repo is temporary abandoned while I finish the python POC, this will eventually be moved to rust** +# Boring Lang The Boring Programming Language (Boring-Lang) is an attempt to create an easy, productive, general purpose programming language that makes as few interesting choices as possible while still being in line with modern concepts in programming languages. -The language (wish list): +The language: * is compiled with a run-time (llvm for convenience + c/rust compatibility) -* has managed memory (via weak pointers and automatic reference counting) -* uses async-await for all IO, with a built-in multi-core scheduler +* has managed memory (via strong/weak pointers and automatic reference counting) +* uses async-await for all IO, with a built-in multi-core scheduler (tokio) * supports algebraic data types (Result type for errors, Maybe/Optional type for nullables) * supports parametric polymorphism (generics) with higher kinded types * uses struct+traits, rather than classes or stuct+interfaces * has a rich standard library (similar scale to python or go) * is immutable by default +* is sandboxed by default + +It's a middle-ground of Rust, Golang, Swift, Typescript, and Python. The goal is not to break any new ground in PL theory, or even create a language anyone likes, but rather to create a language with as few deal-breakers as possible for maximum day-to-day industrial programming ergonomics. + +This language is under active development, progress will be marked here as the language is developed. + +- [x] Functions +- [x] Int Literals +- [x] Float Literals +- [x] Block expression +- [x] Return keyword +- [x] Normal assignment +- [x] Structs + - [x] Define + - [x] Literal + - [x] Getter + - [x] Setter +- [x] Type Aliases +- [ ] Methods + - [x] Declaration + - [ ] Use +- [ ] Traits +- [ ] Generics + - [ ] Basic + - [ ] Higher kinded types +- [ ] Control Flow + - [ ] If + - [ ] While + - [ ] For +- [ ] Enums +- [ ] Lambdas +- [ ] Async-Await +- [ ] Imports +- [ ] Visibility +- [ ] Const / Mut -It's basically a middle-ground of Rust, Golang, Swift, Typescript, and Python. The goal is not to break any new ground in PL theory, or even create a language anyone likes, but rather to create a language with as few deal-breakers as possible for day-to-day industrial programming. ## Http Server Example -``` +```rust import net.http as http import logging as logging import json as json @@ -54,7 +85,7 @@ async fn main(args: Vec[Str], os: OS): I32 { All variables are immutable by default, to make them mutable use the `mut` keyword. Once a variable becomes immutable it cannot become mutable again. If you need it to become mutable, either implement the `clone` trait, or simply create a new one with the same data. -``` +```rust let mut foo = Dict[String, Int32].new(); // constructor returns a mutable reference foo.insert("eggs", 12); foo.insert("bananas", 2); @@ -70,7 +101,7 @@ baz.insert("apples", 4); // fine Methods on a struct must specify if they mutate the struct. -``` +```rust impl Dict[Key: Hashable, Value] { fn insert(self: mut Self, key: Key, value: Value) { // mutate self here @@ -91,10 +122,10 @@ Context is an exceptionally useful feature in golang, but a common complaint is The boring standard library solves this by using parametric polymorphism. Context is by default an empty object passed through the chain, and each function/set of context parameters is an additional trait condition applied at compile time. -``` -type HTTPRequest[Ctx: Context] = async fn(Ctx, http.Request, mut http.Response) +```rust +type HTTPRequest[Ctx: Context] = async fn(Ctx, http.Request, mut http.Response); -pub fn tracing_middleware[Ctx: Tracing](handler: HTTPRequest[Ctx]) HTTPRequest { +pub fn tracing_middleware[Ctx: Tracing](handler: HTTPRequest[Ctx]): HTTPRequest { return async fn(ctx: Ctx, req: http.Request, resp: mut http.Response) { with tracing.Span(ctx, "request_duration") { await handler(ctx, req, resp); @@ -102,7 +133,7 @@ pub fn tracing_middleware[Ctx: Tracing](handler: HTTPRequest[Ctx]) HTTPRequest { }; } -pub fn auth_middleware[Ctx: Auth](handler: HTTPRequest[Ctx], scope: Str) HTTPRequest { +pub fn auth_middleware[Ctx: Auth](handler: HTTPRequest[Ctx], scope: Str): HTTPRequest { return async fn(ctx: Ctx, req: http.Request, resp: mut http.Response) { if ctx.has_scope(scope) { await handler(ctx, req, resp); @@ -112,7 +143,7 @@ pub fn auth_middleware[Ctx: Auth](handler: HTTPRequest[Ctx], scope: Str) HTTPReq }; } -pub fn cancel_middleware[Ctx: Cancel](handler: HTTPRequest[Ctx]) HTTPRequest { +pub fn cancel_middleware[Ctx: Cancel](handler: HTTPRequest[Ctx]): HTTPRequest { return async fn(ctx: Ctx, req: http.Request, resp: mut http.Response) { if !(await ctx.is_cancelled()) { // check cancel token await handler(ctx, req, resp); @@ -129,7 +160,7 @@ for the above examples, you would pass a context type that implements all three Similar to python, folders/files represent the `.` seperated import path, but relative imports are *not* supported. Exported values must be marked with `pub`. All imports take the form: -``` +```rust import package.path as local_name pub type MyStruct struct { @@ -143,7 +174,7 @@ pub type MyStruct struct { `if` is an expression in boring-lang, with the last expression in a block being the return value. -``` +```rust let a = if true { 4 } else { @@ -160,7 +191,7 @@ Conditions do not require parenthesis and *must* evaluate to the Boolean type. Boring-lang supports `for` and `while` loops, with `for` having an `async` variant. `while` loops require an expression of Boolean type, while `for` loops require an expression that implements the `Iter` or `AIter` traits. -``` +```rust let mut i = 0; while i < 100 { i = i + 1; @@ -179,7 +210,7 @@ async for result in paginated_list { `continue` and `break` work similar to other languages. -``` +```rust while true { break; // do nothing } @@ -201,7 +232,7 @@ for i in range(100) { return async with db.transation(ctx) as t { await t.insert(ctx, record); // returns result type -} +}; ``` ### `return` @@ -218,7 +249,7 @@ let result = match number { 1 => 'foo', 3 => 'bar', _ => 'baz', -} +}; // result = 'bar' ``` diff --git a/notes.txt b/notes.txt index a6a1898..60731b8 100644 --- a/notes.txt +++ b/notes.txt @@ -30,29 +30,3 @@ class TypeUsage: if / match return never if all blocks return never; blocks propagate never except at the function level; - - -TODO: -* ~Float Literals~ -* ~Block expression~ -* ~Return keyword~ -* ~Normal assignment~ -* ~Structs~ - * ~Define~ - * ~Literal~ - * ~Getter~ - * ~Setter~ -* ~Type Aliases~ -* Methods - * ~Declaration~ - * Use -* Traits -* Generics -* Enums -* Arrays -* Strings -* Lambdas -* Async -* Imports -* Visibility -* Const / Mut