diff --git a/notes.md b/notes.md index b5b2fb4..c855049 100644 --- a/notes.md +++ b/notes.md @@ -4,15 +4,16 @@ data types: i64, f64 - numbers bool - logical boolean values -{fn [type1 type2 ... -> rettype]} +{fn [type1 type2 ... -> rettype]} / {fn [type1 type2 ...]} => [fn type1 type2 ... rettype] -{array [type length]} +{array [type length]} => [array type length] (struct name ^type1 member1 ^type2 member2 ^type3 member3) -{tuple [^{name member1} type1 ^{name member2} type2 ^{name member3} type3]} +^{tuple [^{name member1} type1 ^{name member2} type2 ^{name member3} type3]} +^{name name} [tuple ^{name member1} type1 ^{name member2} type2 ^{name member3} type3] (enum name (clause1 type1 type2 ...) @@ -22,27 +23,43 @@ bool - logical boolean values ^{tuple [type1 type2 ...]} clause2 ^void clause3]} -(protocol name - (method name [self ^type1 arg1 ^type2 arg2 -> rettype])) - -(impl protocol type - (method name [self ^type1 arg1 ^type2 arg2 -> rettype] - body...)) - Variables have both a datatype and an isolation modifier. There are three possible isolation types: * `const` - this is the default, if no isolation modifier is given. No in-place mutations are possible with `const` values. * `val` - a `val` variable can be mutated in-place, but changes _only_ affect that variable. If it is assigned to any other variable or passed as a parameter, it is copied if necessary and can be treated as a new, totally distinct value. +* `mut` - Only valid on function parameters. Denotes a value in which mutations to the parameter are visible from the calling + function. Any assignments of a `mut` value to other variables (except being further passed as a `mut` parameter) + makes a copy. + +All datatypes can have the following modifiers: + * `ref` - a `ref` is analogous to a full pointer or object reference. Copies of the same `ref` can exist in multiple places, and refer to the same object in memory. Changes to data mutated via a `ref` are immediately visible to any other - code that has the same `ref`. - -When defining data structures, individual members can be annotated as `ref`, but not `const` or `val` - only the structure -as a whole can be `const` or `val`. + code that has the same `ref`. `ref`s are created with the `box` function. References that point in the middle of + a structure are not possible; use a tuple or an enum or something. +* `opt` - equivalent to `(enum [opt type] (some type) none)`, assuming we had generics, which atm we do not. no idea what + destructuring helpers make sense here yet. +* `array` - contiguously-allocated values of any type. size can be dynamically specified, bounds are checked on access. Q: should `const` structures be able to modify `ref` members directly? leaning towards yes. `ref` seems to inherently imply - interior mutability. + interior mutability - after all, the value a given `ref` points to is _not_ constant. + +Interesting thought: we only need GC for `ref`s! local variables + parameters can live in a stack-based arena, and +globals are statically allocated. + +# typed dynamic dispatch + +(protocol name + (method name [^mut self ^type1 arg1 ^type2 arg2 -> rettype])) + +(impl protocol type + (method name [^mut self ^type1 arg1 ^type2 arg2 -> rettype] + body...)) + +# type restrictions + +* `scoped` - would be nice to be able to define destructors and have some kind of RAII, but it's probably overkill # memory management diff --git a/src/main/tock/compiler/type.cljc b/src/main/tock/compiler/type.cljc index c3015f3..9892204 100644 --- a/src/main/tock/compiler/type.cljc +++ b/src/main/tock/compiler/type.cljc @@ -33,7 +33,7 @@ (defn coerce [expr typesym error] (let [ltype (expr-type expr)] (cond (= ltype typesym) expr - (= typesym 'void) (void `(u/cast ~expr)) + (= typesym 'void) (void `(u/cast-void ~expr)) :else (throw error)))) (defn unify [lexpr rexpr error] diff --git a/src/main/tock/compiler/wasm.cljc b/src/main/tock/compiler/wasm.cljc index 329d8e3..d51311c 100644 --- a/src/main/tock/compiler/wasm.cljc +++ b/src/main/tock/compiler/wasm.cljc @@ -73,6 +73,11 @@ (_ ?funcref . !args ...) (concat (mapcat emit-code !args) [[op/call ?funcref]]))) +(defmethod emit-code `u/cast-void [form] + (m/match form + (_ ?expr) + (concat (emit-code ?expr) [[op/drop]]))) + (defmethod emit-code 'do [form] (mapcat #(emit-code %) (rest form)))