diff options
-rw-r--r-- | std/ast.pk | 81 | ||||
-rw-r--r-- | std/async.pk | 19 | ||||
-rw-r--r-- | std/fundamental/ast.pk | 113 | ||||
-rw-r--r-- | std/fundamental/logs.pk | 1 | ||||
-rw-r--r-- | std/logs.pk | 1 | ||||
-rw-r--r-- | std/prelude/format.pk (renamed from std/default/format.pk) | 31 | ||||
-rw-r--r-- | std/prelude/iterators.pk (renamed from std/default/iterators.pk) | 2 | ||||
-rw-r--r-- | std/prelude/options.pk (renamed from std/default/options.pk) | 8 | ||||
-rw-r--r-- | std/prelude/results.pk (renamed from std/default/results.pk) | 2 | ||||
-rw-r--r-- | std/tests.pk (renamed from std/fundamental/tests.pk) | 2 |
10 files changed, 126 insertions, 134 deletions
diff --git a/std/ast.pk b/std/ast.pk new file mode 100644 index 0000000..abc66ba --- /dev/null +++ b/std/ast.pk @@ -0,0 +1,81 @@ +## std.ast: Exposes the AST for building and operating on with macros. + +pub type Expr = union + Ident(string), Number(int), Float(float), Char(chr), String(str) + Struct(list[tuple[field: str, value: Expr]]) + Tuple(list[tuple[field: string?, value: Expr]]) + List(list[Expr]) + Let(id: Pattern, kind: Type?, value: ref Expr) + Var(id: Pattern, kind: Type?, value: ref Expr?) + Const(id: Pattern, kind: Type?, value: ref Expr) + FuncDecl( # effects? + id: str, + generics: list[GenericParams], + params: list[FunctionParams], + kind: Type, + body: list[Expr] + ) + TypeDecl(id: str, generics: list[str], alias: Type) + Module(id: str, body: list[Expr]) + Use(path: str) + Pub(Expr) # can easily generate incoherent statements. still desired? + Call(id: str, params: list[Expr]) + Cond(branches: list[CondBranch], else_body: list[Expr]?) + Try( + try_body: list[Expr], + catches: list[TryBranch] + finally_body: list[Expr]? + ) + Match( + item: ref Expr, + branches: list[MatchBranch] + ) + Block(id: str?, body: list[Expr]) + ConstBlock(body: list[Expr]), + For(binding: Pattern, range: ref Expr, body: list[Expr]) + While(cond: ref Expr, body: list[Expr]) + Loop(body: list[Expr]), + +pub type CondBranch = tuple + cond: Expr + body: list[Expr] + +pub type TryBranch = tuple + exceptions: list[str] + body: list[Expr] + +pub type MatchBranch = tuple + pattern: Pattern + guard: Option[Expr] + body: list[Expr] + +pub type Type = ref union + Void, Never, + Integer, Float, String, + Func(from: Type, to: Type) # todo: multiple parameters + Struct(list[tuple[id: str, kind: Type]]) + Tuple(list[tuple[id: str?, kind: Type]]) + Union(list[tuple[id: str, kind: Type]]) + Interface( # todo: generics + funcs: list[Signature] + for_type: Type? + ) + Array(size: uint, kind: Type) + List(Type) + Slice(Type) # todo: plus ownership + Alias(str) # todo: params?? huh? + Static(Type) + Mutable(Type) + Reference(Type) + Pointer(Type) +pub type Signature = struct # todo: generics + id: str + effect: Option[str] + params: list[Type] + kind: Option[Type] +pub type Pattern = union + Ident(str) + Number(int), Float(float), Char(chr), String(str) + Struct(name: str, params: list[Pattern]) + Tuple(list[Pattern]) + List(list[Pattern]) diff --git a/std/async.pk b/std/async.pk new file mode 100644 index 0000000..7c76076 --- /dev/null +++ b/std/async.pk @@ -0,0 +1,19 @@ +## std.async: Zig-style colourless async/await. +## Future types, the async macro, and the await function. + +## A standard Future type. Opaque. +pub type Future[T] = struct + ... + +## The `async` macro transforms any function call into +## an asynchronous call returning a Future of some type. +pub macro async[T](call: T): Future[T] = + ... + +## The `await` function blocks on a Future[T] call until it returns a value. +pub func await[T](self: Future[T]): T = + ... + +examples: + std.net.connect() + print 1.async.await diff --git a/std/fundamental/ast.pk b/std/fundamental/ast.pk deleted file mode 100644 index 0529cbd..0000000 --- a/std/fundamental/ast.pk +++ /dev/null @@ -1,113 +0,0 @@ -## std/ast: Exposes the AST for building and operating on with macros. - -pub type Ident = string -pub type Number = int -pub type Float = float -pub type Char = char -pub type String = str -pub type Struct = list[struct[field: str, value: Expr]] -pub type Tuple = list[struct[field: Option[string], value: Expr]] -pub type List = list[Expr] - -pub type Let = struct - id: Pattern - kind: Option[Type] - value: ref Expr -pub type Var = struct - id: Pattern - kind: Option[Type] - value: Option[ref Expr] # variable bindings can be delayed -pub type Const = struct - id: Pattern - kind: Option[Type] - value = ref Expr -pub type FuncDecl = struct - public: bool - effect: Option[str] - id: str - generics: list[struct[id: str, kind: Option[Type]]] - params: list[struct[id: str, kind: Type]] - kind: Type - body: list[Expr] -pub type TypeDecl = struct - id: str - generics: list[str] - alias: Type -pub type Import = struct - mod_from: Option[string] - imports: list[str] - alias: Option[str] -pub type Module = struct - id: str - body: list[Expr] - -pub type Call = struct - id: str - params: list[Expr] -pub type Cond = struct - branches: list[struct[cond: Expr, body: list[Expr]]] - else_body: Option[list[Expr]] -pub type Try = struct - body: list[Expr] - catches: list[struct[exceptions: list[str], body: list[Expr]]] - finally_body: Option[list[Expr]] -pub type Match = struct - item: ref Expr - branches: list[struct[pattern: Pattern, guard: Option[Expr], body: list[Expr]]] -pub type Block = struct - id: Option[str] - body: list[Expr] -pub type Static = struct - body: list[Expr] -pub type For = struct - binding: Pattern - range: ref Expr - body: list[Expr] -pub type While = struct - cond: ref Expr - body: list[Expr] -pub type Loop = struct - body: list[Expr] - -# the first style of union. naming anonymous types. -pub type Type = union - Void, Never, - Integer, Float, String, - Func: struct[from, to: ref Type] # todo: multiple parameters - Struct: list[struct[id: str, kind: Type]] - Tuple: list[struct[id: Option[str], kind: Type]] - Union: list[struct[id: str, kind: Type]] - Interface: struct # todo: generics - funcs: list[Signature] - for_type: Option[ref Type] - Array: struct[size: uint, kind: ref Type] - List: ref Type - Slice: ref Type # todo: plus ownership - Alias: str # todo: params?? huh? - Static: ref Type - Mutable: ref Type - Reference: ref Type -pub type Signature = struct # todo: generics - id: str - effect: Option[str] - params: list[Type] - kind: Option[Type] -pub type Pattern = union - Ident: str - Number: int, Float: float, Char: char, String: str - Struct: struct[name: str, params: list[Pattern]] - Tuple: list[Pattern] - List: list[Pattern] - -# the second style of union. A union of literal types, no names. -pub type Expr = union - Ident, Number, Float, Char, String, Struct, Tuple, List, - Let, Var, Const, FuncDecl, TypeDecl, Import, Module, - Call, Cond, Try, Match, Block, Static, For, While, Loop, - -# todo: decide on a style of union - -# anonymous struct objects can be constructed with {} -# anonymous tuple objects can be constructed with () -# anonymous list objects can be constructed with [] -# anonymous union *types* can be constructed with | (in parameters) diff --git a/std/fundamental/logs.pk b/std/fundamental/logs.pk deleted file mode 100644 index 7a0060f..0000000 --- a/std/fundamental/logs.pk +++ /dev/null @@ -1 +0,0 @@ -## std/logs: Utility macros and functions for logging. diff --git a/std/logs.pk b/std/logs.pk new file mode 100644 index 0000000..98042b0 --- /dev/null +++ b/std/logs.pk @@ -0,0 +1 @@ +## std.logs: Utility macros and functions for logging. diff --git a/std/default/format.pk b/std/prelude/format.pk index b117632..3adb68b 100644 --- a/std/default/format.pk +++ b/std/prelude/format.pk @@ -1,8 +1,8 @@ -## std/format: Niceties around printing and debugging. +## std.format: Niceties around printing and debugging. ## This module is imported by default. ## The Display interface. Any type implementing `str` is printable. -## Any type that is Display must also implement Debug. +## Any type that is Display must necessarily also implement Debug. pub type Display = interface str(Self): str dbg(Self): str @@ -29,24 +29,25 @@ pub func dbg(self: str): str = "\"" & self & "\"" ## An implementation of the Debug interface for all structs. ## Uses the special `struct` typeclass. pub func dbg(self: struct): str = - "{" & self.fields.map(field => field.id & field.value.dbg) & "}" + "{{}}".fmt(self.fields.map((key, val) => key & ":" & val.dbg)) ## An implementation of the Debug interface for all tuples. ## Uses the special `tuple` typeclass. pub func dbg(self: tuple): str = - result &= "(" - for i, field in self.fields.enumerate(): - result &= field.id.map(id => id & " = ").get_or("") - if i != self.fields.len: - result &= ", " - result &= ")" + "({})".fmt(self.fields.map((key, val) => + key.map(x => x & ":").get_or("") & val.dbg).join(", ")) ## An implementation of the Debug interface for all arrays and lists. -pub func dbg(self: Iter[Debug]): str = - "[" & self.map(x => x.str).join(", ") & "]" +pub func dbg[T: Debug](self: Iter[T]): str = + "[{}]".fmt(self.map(x => x.str).join(", ")) ## The fmt macro. Builds a formatted string from its arguments. -pub macro fmt(formatted: static[str], args: varargs[Display]) = - # if not formatted of String: - # macro_error("fmt must take a static string parameter!") - ... +pub macro fmt(self: static[str], args: varargs[Display]): str = + let parts = self.split("{}") + if parts.len != args.len + 1: + macro_error("wrong number of arguments") + use std.ast + result = parts.get(0)! + for i, arg in args: + result &= quote(`parts` & str(`arg`) &) # fixme + result &= parts.last()! diff --git a/std/default/iterators.pk b/std/prelude/iterators.pk index f7e4972..224460f 100644 --- a/std/default/iterators.pk +++ b/std/prelude/iterators.pk @@ -1,4 +1,4 @@ -## std/iterators: The Iter interface and associated functions. +## std.iterators: The Iter interface and associated functions. ## This module is imported by default. ## The Iter interface. Any type implementing `next()` is iterable. diff --git a/std/default/options.pk b/std/prelude/options.pk index fb696ba..4f6cef2 100644 --- a/std/default/options.pk +++ b/std/prelude/options.pk @@ -1,4 +1,4 @@ -## std/options: Optional types. +## std.options: Optional types. ## This module is imported by default. use std.format @@ -54,10 +54,14 @@ pub func flatten[T](self: Option[Option[T]]): Option[T] = pub func get_or[T](self: Option[T], default: T): T = if self of Some(x): x else: default + +## A dummy type signalling the empty value +type EmptyType = distinct unit + ## Directly accesses the inner value. Throws an exception if None. pub func ![T](self: Option[T]): T = if self of Some(x): x - else: raise Exception # todo: syntax?? + else: raise EmptyType ## Indirect access. Propagates `None`. ## Parsed by compiler magic. diff --git a/std/default/results.pk b/std/prelude/results.pk index 8e21234..1209b40 100644 --- a/std/default/results.pk +++ b/std/prelude/results.pk @@ -1,4 +1,4 @@ -## std/results: Result types. +## std.results: Result types. ## This module is imported by default. use std[options, format] diff --git a/std/fundamental/tests.pk b/std/tests.pk index 7eb00a8..8d13a4e 100644 --- a/std/fundamental/tests.pk +++ b/std/tests.pk @@ -1,4 +1,4 @@ -## std/tests: Utility macros and functions for testing. +## std.tests: Utility macros and functions for testing. ## A macro for runnable examples. Runs them on compilation. pub macro examples(body) = |