updated readme
This commit is contained in:
50
README.md
50
README.md
@@ -5,11 +5,11 @@
|
|||||||
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 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 (wish list):
|
||||||
* is compiled with a run-time (llvm for convenience + c compatibility)
|
* is compiled with a run-time (llvm for convenience + c/rust compatibility)
|
||||||
* is garbage collected
|
* is garbage collected
|
||||||
* uses async-await for all IO, with a built-in multi-core scheduler
|
* uses async-await for all IO, with a built-in multi-core scheduler
|
||||||
* supports algebraic data types (Result type for errors, Maybe/Optional type for nullables)
|
* supports algebraic data types (Result type for errors, Maybe/Optional type for nullables)
|
||||||
* supports parametric polymorphism
|
* supports parametric polymorphism (generics)
|
||||||
* uses struct+traits, rather than classes or stuct+interfaces
|
* uses struct+traits, rather than classes or stuct+interfaces
|
||||||
* has a rich standard library (http server, actor model)
|
* has a rich standard library (http server, actor model)
|
||||||
* is immutable by default
|
* is immutable by default
|
||||||
@@ -46,22 +46,20 @@ async func main(args: Array<Str>) Int32 {
|
|||||||
|
|
||||||
## Mutability
|
## Mutability
|
||||||
|
|
||||||
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 `copy` trait, or simply create a new one with the same data.
|
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.
|
||||||
|
|
||||||
```
|
```
|
||||||
let mut foo := Dict<String, Int32>{
|
let mut foo = Dict<String, Int32>() // constructors always return a mutable reference
|
||||||
'eggs': 12,
|
foo.insert("eggs", 12)
|
||||||
'bananas': 2,
|
foo.insert("bananas", 2)
|
||||||
}
|
foo.insert("grapes", 2)
|
||||||
// fine
|
|
||||||
foo.insert('grapes', 2)
|
|
||||||
|
|
||||||
let bar = foo // bar is not mutable
|
let bar = foo // bar is not mutable
|
||||||
|
|
||||||
bar.insert('apples', 4) // fails with compiler error
|
bar.insert("apples", 4) // fails with compiler error
|
||||||
|
|
||||||
let mut baz = bar.copy()
|
let mut baz = bar.clone()
|
||||||
baz.insert('apples', 4) // fine
|
baz.insert("apples", 4) // fine
|
||||||
```
|
```
|
||||||
|
|
||||||
Methods on a struct must specify if they mutate the struct.
|
Methods on a struct must specify if they mutate the struct.
|
||||||
@@ -72,7 +70,7 @@ impl Dict<Key: Hashable, Value> {
|
|||||||
// mutate self here
|
// mutate self here
|
||||||
}
|
}
|
||||||
|
|
||||||
func get(self: Dict, key: Key) {
|
func get(self: Dict, key: Key) Optional<Value> {
|
||||||
// no need for `mut`
|
// no need for `mut`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,31 +88,31 @@ The boring standard library solves this by using parametric polymorphism. Contex
|
|||||||
```
|
```
|
||||||
type HTTPRequest<Ctx: Context> = async func(Ctx, http.Request, mut http.Response)
|
type HTTPRequest<Ctx: Context> = async func(Ctx, http.Request, mut http.Response)
|
||||||
|
|
||||||
pub func tracing_middleware<Ctx: Tracing>(handler: HTTPRequest<Ctx>){
|
pub func tracing_middleware<Ctx: Tracing>(handler: HTTPRequest<Ctx>) HTTPRequest {
|
||||||
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
||||||
with tracing.NewSpan(ctx, 'request_duration') {
|
with tracing.Span(ctx, "request_duration") {
|
||||||
await handler(ctx, req, resp)
|
await handler(ctx, req, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub func auth_middleware<Ctx: Auth>(handler: HTTPRequest<Ctx>, scope: Str){
|
pub func auth_middleware<Ctx: Auth>(handler: HTTPRequest<Ctx>, scope: Str) HTTPRequest {
|
||||||
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
||||||
if ctx.has_scope(scope) {
|
if ctx.has_scope(scope) {
|
||||||
await handler(ctx, req, resp)
|
await handler(ctx, req, resp)
|
||||||
}
|
}
|
||||||
await resp.set_status(403)
|
await resp.set_status(403)
|
||||||
await resp.write('missing scope')
|
await resp.write("missing scope")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub func cancel_middleware<Ctx: Cancel>(handler: HTTPRequest<Ctx>){
|
pub func cancel_middleware<Ctx: Cancel>(handler: HTTPRequest<Ctx>) HTTPRequest {
|
||||||
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
return async func(ctx: Ctx, req: http.Request, resp: mut http.Response) {
|
||||||
if !(await ctx.is_cancelled()) { // check cancel token
|
if !(await ctx.is_cancelled()) { // check cancel token
|
||||||
await handler(ctx, req, resp)
|
await handler(ctx, req, resp)
|
||||||
}
|
}
|
||||||
await resp.set_status(400)
|
await resp.set_status(400)
|
||||||
await resp.write('cancelled')
|
await resp.write("cancelled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -123,18 +121,22 @@ for the above examples, you would pass a context type that implements all three
|
|||||||
|
|
||||||
## Monadic function modifiers
|
## Monadic function modifiers
|
||||||
|
|
||||||
Boring uses function modifiers to implement functionality like `async/await` and `coroutines`. These function by rewriting the AST prior to compilation. The table below describes the modifiers currently available.
|
Boring uses function modifiers to implement functionality like `async/await` and `coroutines`. These function by [rewriting the code into a state machine](https://tmandry.gitlab.io/blog/posts/optimizing-await-1/) prior to compilation. The table below describes the modifiers currently available.
|
||||||
|
|
||||||
|Type|Change To Return Type|Introduces to Scope|
|
|Type|Change To Return Type|Introduces to Scope|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|async|`Promise<ReturnType>`|await|
|
|`async`|`Promise<ReturnType>`|`await`|
|
||||||
|coroutine|`FirstReturnType,func(Next,Params)...`|yield|
|
|`coroutine`|`FirstReturnType,func(Next,Params)...`|`yield`|
|
||||||
|errors<ErrorType>|`Result<ReturnType,ErrorType>`|?|
|
|`error<ErrorType>`|`Result<ReturnType,ErrorType>`|`?`|
|
||||||
|
|
||||||
## Import System
|
## Import System
|
||||||
|
|
||||||
Similar to python, folders/files represent the `.` seperated import path though relative imports are *not* supported. Exported values must be marked with `pub`. All imports take the form:
|
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:
|
||||||
|
|
||||||
```
|
```
|
||||||
import package.path as local_name
|
import package.path as local_name
|
||||||
|
|
||||||
|
pub struct MyStruct {
|
||||||
|
id: Int
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user