From 199d8bbc6d5793d895311cb0d2296f3e1279a3e0 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 10 May 2024 00:54:48 -0700 Subject: std: replace static with const, fix std.ast --- std/ast.pk | 29 +++++++++++++++++++---------- std/async.pk | 1 + std/prelude/arrays.pk | 14 +++++++------- std/prelude/clone.pk | 2 +- std/prelude/format.pk | 4 ++-- std/prelude/lists.pk | 2 +- std/prelude/options.pk | 2 +- std/prelude/strings.pk | 1 + 8 files changed, 33 insertions(+), 22 deletions(-) diff --git a/std/ast.pk b/std/ast.pk index b069aa9..4b8a783 100644 --- a/std/ast.pk +++ b/std/ast.pk @@ -1,5 +1,8 @@ ## std.ast: Exposes the AST for building and operating on with macros. +## The `Expr` type represents the abstract syntax tree of Puck itself. +## It notably lacks type information. +## It is, however, syntactically correct-by-construction. pub type Expr = union Ident(string) Number(int) @@ -11,17 +14,24 @@ pub type Expr = union 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) + ConstDecl(public: bool, id: Pattern, kind: Type?, value: ref Expr) FuncDecl( # effects? + public: bool, id: str, - generics: list[GenericParams], - params: list[FunctionParams], - kind: Type, + generics: list[(id: Pattern, kind: Type?)], + params: list[(id: Pattern, kind: Type)], + kind: Type?, body: list[Expr]) - TypeDecl(id: str, generics: list[str], alias: Type) - Module(id: str, body: list[Expr]) + MacroDecl( + public: bool, + id: str, + generics: list[(id: Pattern, kind: Type?)], + params: list[(id: Pattern, kind: Type?)], + kind: Type?, + body: list[Expr]) + TypeDecl(public: bool, id: str, generics: list[str], alias: Type) + Module(public: bool, 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[(cond: Expr, body: list[Expr])], @@ -34,13 +44,12 @@ pub type Expr = union item: ref Expr, branches: list[(pattern: Pattern, guard: Expr?, body: list[Expr])]) Block(id: str?, body: list[Expr]) - ConstBlock(body: list[Expr]), + ConstExpr(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 Type = ref union - Void Never Int(size: uint) Dec(size: uint) @@ -58,7 +67,7 @@ pub type Type = ref union List(Type) Slice(Type) # todo: plus ownership Alias(str) # todo: params?? huh? - Static(Type) + Const(Type) Lent(Type) Mut(Type) Ref(Type) diff --git a/std/async.pk b/std/async.pk index f2ae3e0..87b1abc 100644 --- a/std/async.pk +++ b/std/async.pk @@ -3,6 +3,7 @@ # reference: https://kristoff.it/blog/zig-colorblind-async-await/ ## A standard Future type. Opaque. +@[opaque] pub type Future[T] = struct ... diff --git a/std/prelude/arrays.pk b/std/prelude/arrays.pk index 6f57865..d8512dd 100644 --- a/std/prelude/arrays.pk +++ b/std/prelude/arrays.pk @@ -3,28 +3,28 @@ ## Primitive fixed-size arrays. Their size is statically known at compile-time. @[magic] -pub type array[T, size: static uint] +pub type array[T, size: const uint] ## Array access. Returns None if i is out of range. @[magic] -pub func get[T, size: static uint](self: lent array[T, size], i: uint): lent T? +pub func get[T, size: const uint](self: lent array[T, size], i: uint): lent T? ## Array access. Returns None if i is out of range. @[magic] -pub func get[T, size: static uint](self: mut array[T, size], i: uint): mut T? +pub func get[T, size: const uint](self: mut array[T, size], i: uint): mut T? ## Array mutation. # todo: how do we detect range errors? @[magic] -pub func set[T, size: static uint](self: mut array[T, size], i: uint, val: T): Success[IndexOutOfBounds] +pub func set[T, size: const uint](self: mut array[T, size], i: uint, val: T): Success[IndexOutOfBounds] ## A helper function to get the length of an array. ## Known to the compiler, and computed at compile-time. @[inline] -pub func len[T, size: static uint](self: lent array[T, size]): uint = size +pub func len[T, size: const uint](self: lent array[T, size]): uint = size -type ArrayIter[T, size: static uint] = struct +type ArrayIter[T, size: const uint] = struct ... -pub func iter[T, size: static uint](self: array[T, size]): ArrayIter[T, S] = +pub func iter[T, size: const uint](self: array[T, size]): ArrayIter[T, S] = ... # todo: Eq, PartialEq, Ord, PartialOrd diff --git a/std/prelude/clone.pk b/std/prelude/clone.pk index 5d11cdb..0ddfcf6 100644 --- a/std/prelude/clone.pk +++ b/std/prelude/clone.pk @@ -18,7 +18,7 @@ pub func clone[T: Clone](self: tuple[T]): tuple[T] = ... ## Implementation of `clone` for arrays of any size. -pub func clone[T: Clone, size: static[uint]](self: array[T, size]): array[T, size] = +pub func clone[T: Clone, size: const uint](self: array[T, size]): array[T, size] = var res: array[T, size] for i in 0 .. size do res.push(self.i.clone) diff --git a/std/prelude/format.pk b/std/prelude/format.pk index 6fc7c99..3bb5825 100644 --- a/std/prelude/format.pk +++ b/std/prelude/format.pk @@ -21,7 +21,7 @@ pub func print(params: varargs[Display]) = ## Note: this function is special! It does not count as a side effect. ## This breaks effect tracking, of course: but `dbg` is for debugging. ## It will produce a warning in code compiled for release. -@[no_side_effect] +@[pure] pub func dbg(params: varargs[Debug]) = stdout.write(params.map(x => x.dbg).join(" "), "\n") @@ -46,7 +46,7 @@ pub func dbg[T: Debug](self: Iter[T]): str = "[{}]".fmt(self.map(x => x.dbg).join(", ")) ## The fmt macro. Builds a formatted string from its arguments. -pub macro fmt(self: static[str], args: varargs[Display]): str = +pub macro fmt(self: const str, args: varargs[Display]): str = let parts = self.split("{}") if parts.len != args.len + 1 then macro_error("wrong number of arguments") diff --git a/std/prelude/lists.pk b/std/prelude/lists.pk index 57de91b..1bce693 100644 --- a/std/prelude/lists.pk +++ b/std/prelude/lists.pk @@ -4,7 +4,7 @@ ## The fundamental list type. Heap-allocated. ## Equivalent to Vec in other languages. -@[unsafe] # unsafe on a struct tells us raw field access breaks invariants. +@[opaque] # opaque on a struct tells us raw field access breaks invariants. pub type list[T] = struct data: ptr T capacity: int diff --git a/std/prelude/options.pk b/std/prelude/options.pk index d5cfb9d..4825803 100644 --- a/std/prelude/options.pk +++ b/std/prelude/options.pk @@ -19,7 +19,7 @@ pub func ![T](self: T?): T = else raise "empty" ## Indirect access. Propagates `None`. -pub macro ?[T](self: T?) = +pub macro ?[T](self: Option[T]) = quote match `self` of Some(x) then x diff --git a/std/prelude/strings.pk b/std/prelude/strings.pk index e86d520..a8c72fb 100644 --- a/std/prelude/strings.pk +++ b/std/prelude/strings.pk @@ -6,6 +6,7 @@ ## ## We do not want methods defined on `list[byte]` to carry over, ## so we define `str` as a newtype. +@[opaque] pub type str = struct data: list[byte] -- cgit v1.2.3-70-g09d2