aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJJ2023-12-30 00:03:06 +0000
committerJJ2023-12-30 00:03:06 +0000
commitb8445b011d9b2a287af0e014998c42525a7fd315 (patch)
tree1b1008c2df5902fae12f40a394113a6453da2a4b
parent774a35ae21dada36af48ae32c862b22587fba107 (diff)
std: restructure, refactor std.ast
-rw-r--r--std/ast.pk81
-rw-r--r--std/async.pk19
-rw-r--r--std/fundamental/ast.pk113
-rw-r--r--std/fundamental/logs.pk1
-rw-r--r--std/logs.pk1
-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) =