[NO TESTS] WIP

This commit is contained in:
Reid D. 'arrdem' McKenzie 2022-06-13 11:44:28 -06:00
parent 0075c4c9f8
commit bc7cb3e909
7 changed files with 479 additions and 103 deletions

View file

@ -0,0 +1,66 @@
use <casters.scad>
module beam($fn=$fn) {
union() {
translate([2, 0, 0])
cube([24, 2, 4]);
translate([26, 0, 2])
rotate([-90, 0, 0])
cylinder(r=2, h=2, $fn=$fn);
}
}
module top() {
translate([0, 0, 4])
cube([24, 96, 0.75]);
translate([0, 2, 0])
beam();
translate([0, 48, 0])
beam();
translate([0, 94, 0])
beam();
}
module worktop() {
translate([0, 0, 40]) {
translate([6, 0, 0])
cube([14, 2, 4]);
translate([6, 92, 0])
cube([14, 2, 4]);
top();
// the wing
translate([52, 96, 0])
rotate([0, 0, 180])
top();
// supports
translate([0, 0, -4]) {
}
}
for(x=[2, 20])
for(y=[0, 92])
translate([x, y, 0])
cube([4, 2, 44]);
translate([6, 0, 0])
cube([14, 2, 4]);
translate([0, 2, 0])
cube([24, 2, 4]);
translate([6, 92, 0])
cube([14, 2, 4]);
translate([0, 94, 0])
cube([24, 2, 4]);
}
worktop();

View file

@ -0,0 +1,150 @@
// 2x4" nominal lumber is really 38mm x 89mm x Z
// Drawing unit: MM 1:1
use <casters.scad>
function in2mm(x) = 25.4 * x;
module txf(height) {
cube([38, 89, height]);
}
module post(height) {
txf(height);
}
module dpost(height) {
post(height);
translate([38, 0, 0])
post(height);
}
module frame(width, depth, height) {
translate([38, 38, 0]) {
dpost(height);
}
translate([38, 38 + 89 + in2mm(30), 0]) {
dpost(height);
}
translate([38, depth - 89 - 38, 0]) {
dpost(height);
}
// bottom bar
translate([0, 0, 89])
rotate([-90, 0, 0])
txf(depth);
// top bar
let(inset=in2mm(30) + 38 + 89) {
translate([0, inset, height])
rotate([-90, 0, 0])
txf(depth - inset);
}
// support
translate([0, 0, height - in2mm(20)])
rotate([-90, 0, 0])
txf(in2mm(30) + 38 * 2 + 89 * 2);
}
module shelf(width, depth, thickness) {
// FIXME: Is there more shelf geometry? A bottom box in 1x2 or something?
cube([width, depth, thickness]);
}
module bench(width, depth, height,
top_thickness=in2mm(0.75),
shelf_width=in2mm(30),
shelf_depth=in2mm(20)) {
ch = 38 * 2 + 2;
ph = height - ch - top_thickness;
// The frame, at relative to caster plane coordinates.
translate([0, 0, ch]) {
frame(width, depth, ph);
translate([width, 0, 0])
mirror([1, 0, 0])
frame(width, depth, ph);
// top
translate([0, 38 + 89 + in2mm(30), ph]) {
cube([width, depth - 38 - 89 - shelf_width, top_thickness]);
}
translate([0, 0, ph]) {
cube([width, 38 + 89, top_thickness]);
}
// Wing top
// bottom bars
translate([38, 38, 89])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, depth, 89])
rotate([-90, 0, -90])
txf(width - 38 * 2);
// "top" bars
translate([38, 38, ph - shelf_depth])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, 38, ph])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, 38, ph - shelf_depth])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, 38*2 + 89*2 + shelf_width, ph - in2mm(20)])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, 38*2 + 89*2 + shelf_width, ph])
rotate([-90, 0, -90])
txf(width - 38 * 2);
translate([38, depth, ph])
rotate([-90, 0, -90])
txf(width - 38 * 2);
// Reference shelf
translate([0, 38 + 89, ph - shelf_depth/2])
shelf(width, shelf_width, top_thickness);
}
// The casters, at absolute coordinates
for (dx=[0, width-(38*3)])
for (dy=[38, 38 + 89 + in2mm(30), depth-38-89])
translate([dx + 38, dy + 89/2, 0])
caster(
// wheel (r, h)
38, 30,
// axel (r, h)
5, 1,
// bearing (r, h)
10, 1,
$fn=16
);
}
module worktop2() {
// 1:1mm to 1:1in because I want to consume this model in the 1:1in garage sketch
scale([1/25.4, 1/25.4, 1/25.4]) {
bench(in2mm(32), in2mm(96), in2mm(40), in2mm(0.75));
}
}
worktop2();

View file

@ -1,6 +1,7 @@
zapp_binary( zapp_binary(
name = "updater", name = "updater",
main = "src/python/arrdem/updater/__main__.py", main = "src/python/arrdem/updater/__main__.py",
shebang = "/usr/bin/env python3",
imports = [ imports = [
"src/python", "src/python",
], ],

212
projects/shoggoth/DOC.md Normal file
View file

@ -0,0 +1,212 @@
# "Documentation"
## Ichor ISA
### TRUE
```() -> (bool)```
Push the constant TRUE onto the stack.
### FALSE
```() -> (bool)```
Push the constant FALSE onto the stack.
### IF <target>
```(bool) -> ()```
Branch to another point if the top item of the stack is TRUE. Otherwise fall through.
Note that not, and, or, xor etc. can all be user or prelude defined functions given if.
### GOTO <target>
```() -> ()```
Branch to another point within the same bytecode segment. The target MUST be within the same module range as the
current function. Branching does NOT update the name or module of the current function.
### DUP <n>
```(A, B, ...) -> (A, B, A, B, ...)```
Duplicate the top N items of the stack.
### ROT <n>
```(A, B, ..., Z) -> (Z, A, B, ...)```
Rotate the top N elements of the stack by 1.
FIXME: What if you want to rotate by more than 1?
### DROP <n>
```(...: n, ...) -> (...)```
Drop the top N items of the stack.
### SLOT <n>
```(..., A) -> (A, ..., A)```
Copy the Nth (counting up from 0 at the bottom of the stack) item to the top of the stack.
Intended to allow users to emulate (immutable) frame locals for reused values.
### IDENTIFIERC <val>
```() -> (IDENTIFIER)```
An inline constant which produces an identifier to the stack.
Identifiers name functions, fields and types but are not strings.
They are a VM-internal naming structure with reference to the module.
#### Function identifiers
Function identifiers are written `<typevars>;<name>;<arglist>;<retlist>`.
For example the signature of `not` is `;not;bool;bool`.
Note that this name scheme allows for `;or;bool,bool;bool` and `;or;bool,bool,bool;bool` to co-exist simultaneously, and for overloading of names with type variables.
One could also have written `or` as `T;or;<funref T;bool>,T,T;T` if one were able to provide a truly generic test
This design is a deliberate reaction to the JVM which does not permit such name-overloading and is intended to enable semi-naive compilation of complex generic operations without munging or erasure.
#### Type identifiers
Type identifiers are written `<typevars>;<name>;<variantlist>`
For example the signature of `bool` is `;bool;<true>,<false>`
As with functions, this allows for generic overloading of names.
For example one could define `tuple` as `;tuple;<tuple>`, `A;tuple;<tuple A>`, `A,B;tuple;<tuple A,B>`, and soforth simultaneously.
### FUNREF
```(IDENTIFIER) -> (<FUNREF ... A; ... B>)```
Note that `;` ends a list here the arguments list and should be read as `to`.
Construct a reference to a static codepoint.
### CALLF <nargs>
```(<FUNREF ... A; ... B>, ... A) -> (... B)```
Call [funref]
Make a dynamic call to the function reference at the top of stack.
The callee will see a stack containg only the provided `nargs`.
A subsequent RETURN will return execution to the next point.
Executing a `CALL` pushes the name and module path of the current function.
### RETURN <nargs>
```(...) -> ()```
Return to the source of the last `CALL`. The returnee will see the top `nargs` values of the present stack
appended to theirs. All other values on the stack will be discarded.
Executing a `RETURN` pops (restores) the name and module path of the current function back to that of the caller.
If the call stack is empty, `RETURN` will exit the interpreter.
### CLOSUREF <nargs>
```(FUNREF<A, ... B; ... C>, A) -> (CLOSURE<... B; ... C>)```
Construct a closure over the function reference at the top of the stack. This may produce nullary closures.
### CLOSUREC <nargs>
```(CLOSURE<A, ... B; ... C>, A) -> (CLOSURE<... B; ... C>)```
Further close over the closure at the top of the stack. This may produce nullary closures.
### CALLC <nargs>
```(CLOSURE<... A; .. B>, ... A) -> (... B)```
Call [closure]
Make a dynamic call to the closure at the top of stack.
The callee will see a stack containg only the provided `nargs` and closed-overs.
A subsequent RETURN will return execution to the next point.
Executing a `CALL` pushes the name and module path of the current function.
### TYPEREF
```(IDENTIFIER) -> (TYPEREF)```
Produces a TYPEREF to the type named by the provided IDENTIFIER.
### FIELDREF
```(IDENTIFIER, TYPEREF) -> (FIELDREF)```
Produces a FIELDREF to the field named by the provided IDENTIFIER.
The FIELDREF must be within and with reference to a sum type.
### VARIANTREF
```(IDENTIFIER, TYPEREF) -> (VARIANTREF)```
Produce a VARIANTREF to an 'arm' of the given variant type.
### STRUCT <nargs>
```(STRUCTREF<S>, ...) -> (S)```
Consume the top N items of the stack, producing a struct of the type `structref`.
The name and module path of the current function MUST match the name and module path of `structref`.
The arity of this opcode MUST match the arity of the struct.
The signature of the struct MUST match the signature fo the top N of the stack.
### FLOAD
```(FIELDREF<f T S>, S) -> (T)```
Consume the struct reference at the top of the stack, producing the value of the referenced field.
### FSTORE
```(FIELDREF<f T S>, S, T) -> (S)```
Consume the struct reference at the top of the stack and a value, producing a new copy of the struct in which
that field has been updated to the new value.
### VARIANT <nargs>
```(VARIANTREF<a A B>, ...) -> (B)```
Construct an instance of an 'arm' of a variant.
The type of the 'arm' is considered to be the type of the whole variant.
The name and module path of the current function MUST match the name and module path of `VARIANTREF`.
The arity of this opcode MUST match the arity of the arm.
The signature of the arm MUST match the signature fo the top N of the stack.
### VTEST
```(VARIANTREF<a A B>, B) -> (bool)```
Test whether B is a given arm of a variant A .
### VLOAD
```(VARIANTREF<a A B>, B) -> (A)```
Load the value of the variant arm.
VLOAD errors (undefined) if B is not within the variant.
VLOAD errors (undefined) if the value in B is not an A - use VTEST as needed.
### ARRAY <nargs>
```(TYPEREF<Y>, ... ∈ Y) -> (ARRAY<Y>)```
Consume the top N items of the stack, producing an array of the type `typeref`.
### ALOAD
```(ARRAY<T>, NAT) -> (T)```
Consume a reference to an array and an index, producing the value at that index.
FIXME: Or a signal/fault.
### ASTORE
```(ARRAY<T>, NAT, T) -> (ARRAY<T>)```
Consume a value T, storing it at an index in the given array.
Produces the updated array as the top of stack.
### BREAK
Abort the interpreter
## Appendix
https://wiki.laptop.org/go/Forth_stack_operators
https://www.forth.com/starting-forth/2-stack-manipulation-operators-arithmetic/
https://docs.oracle.com/javase/specs/jvms/se18/html/jvms-6.html#jvms-6.5.swap

View file

@ -4,9 +4,49 @@
> >
> ~ Charlie Stross, "A Colder War" > ~ Charlie Stross, "A Colder War"
Shoggoth is a language designed to provide highly durable, portable agents. > The greatest performance improvement of all is when a system goes from not-working to working.
>
> ~ John Ousterhout
Shoggoth runs atop a custom platform named Ichor, which aims to trivialize providing these properties. Shoggoth is a language designed to provide highly durable, portable processes.
Much like Eve, it's intended to be an experiment at enabling classes of programs and making some hard things easier.
Shoggoth runs atop a custom platform named Ichor, which aims to trivialize providing these properties and help the implementer focus by eliminating context.
## Ichor
The Ichor virtual machine is a toy.
The implementation presented here is merely as an experimental platform providing a "clean slate" target for compilation.
Ichor should be somewhat familiar to students of JVM bytecode, Fourth or UXN but has different priorities.
Ichor is perhaps best explained as a reaction to the JVM.
To be clear, the JVM is an incredible success story.
But it has some decisions baked in that can't be walked back, such as the existence of `Object.equals()` and the primacy of classes for structuring both data and code.
Ichor exists because it's much easier to define "snapshotting" the state of a flat loop bytecode interpreter with a stack than a recursive interpreter.
The objectives of building durable and portable processes/actors in Shoggoth requires the ability to take a snapshot of program state and persist it to a shared store for REMOTE or EVENTUAL resumption.
Think call/cc except with suspend or await happening across a network and database and scheduler boundary.
Like the JVM, Ichor is a high-level 'struct' or 'object' oriented VM.
Unlike the JVM which provides generics by using type erasure founded on casts and a shared bottom type (`Object`), Ichor has no `null` or ⊥ type.
Ichor has only user-defined closed variant types and structs without inheritance or methods.
Unlike the JVM, Ichor names "functions" and "types" including their generic parameters.
This allows for pervasive name overloading on both argument and return signature without the need for renaming or munging.
Unlike the JVM, Ichor does not make mutability readily available.
There is no concept of a mutable local value, or of a mutable variant or struct.
"Place oriented programming" can be achieved only through explicit use of a mutable reference type which cannot be defined by the user.
This is a bet that a platform founded on pervasive forwarding of immutability can prove viable.
It may not pan out.
Unlike most VMs, Ichor makes no effort to make user-defined C extensions easy.
They're likely to remain difficult-to-impossible as they conflict directly with other design priorities.
## Shoggoth
The Shoggoth language is an ML in Lisp's clothing.
While notationally a Lisp due entirely to the implementer's preference, Shoggoth has far more in common with an ML or other statically and generically typed language than with a unityped Lisp or interpreted language.
## License ## License

View file

@ -146,17 +146,10 @@ XOR3 = BOOTSTRAP.define_function(
] ]
) )
TRUE = BOOTSTRAP.define_type(
"true",
ProductExpr([]),
)
FALSE = BOOTSTRAP.define_type(
"false",
ProductExpr([]),
)
BOOL = BOOTSTRAP.define_type( BOOL = BOOTSTRAP.define_type(
"bool", ";bool",
SumExpr([TRUE, FALSE]) {
";true;": [],
";false;": [],
},
) )

View file

@ -192,15 +192,6 @@ class Opcode:
""" """
class FIELDREF(t.NamedTuple):
"""(IDENTIFIER, TYPEREF) -> (FIELDREF)
Produces a FIELDREF to the field named by the provided IDENTIFIER.
The FIELDREF must be within and with reference to a sum type.
"""
class VARIANTREF(t.NamedTuple): class VARIANTREF(t.NamedTuple):
"""(IDENTIFIER, TYPEREF) -> (VARIANTREF) """(IDENTIFIER, TYPEREF) -> (VARIANTREF)
@ -208,37 +199,6 @@ class Opcode:
""" """
class STRUCT(t.NamedTuple):
"""(STRUCTREF<S>, ...) -> (S)
Consume the top N items of the stack, producing a struct of the type `structref`.
The name and module path of the current function MUST match the name and module path of `structref`.
The arity of this opcode MUST match the arity of the struct.
The signature of the struct MUST match the signature fo the top N of the stack.
"""
nargs: int = 0
class FLOAD(t.NamedTuple):
"""(FIELDREF<f ⊢ T ∈ S>, S) -> (T)
Consume the struct reference at the top of the stack, producing the value of the referenced field.
"""
fieldref: str
class FSTORE(t.NamedTuple):
"""(FIELDREF<f ⊢ T ∈ S>, S, T) -> (S)
Consume the struct reference at the top of the stack and a value, producing a new copy of the struct in which
that field has been updated to the new value.
"""
fieldref: str
class VARIANT(t.NamedTuple): class VARIANT(t.NamedTuple):
"""(VARIANTREF<a ⊢ A ⊂ B>, ...) -> (B) """(VARIANTREF<a ⊢ A ⊂ B>, ...) -> (B)
@ -268,50 +228,8 @@ class Opcode:
""" """
####################################################################################################
# Arrays
####################################################################################################
class ARRAY(t.NamedTuple):
"""(*) -> (ARRAY<Y>)
Consume the top N items of the stack, producing an array of the type `typeref`.
"""
typeref: str
nargs: int
class ALOAD(t.NamedTuple):
"""(ARRAY<T>, NAT) -> (T)
Consume a reference to an array and an index, producing the value at that index.
FIXME: Or a signal/fault.
"""
class ASTORE(t.NamedTuple):
"""(ARRAY<T>, NAT, T) -> (ARRAY<T>)
Consume a value T, storing it at an index in the given array.
Produces the updated array as the top of stack.
"""
####################################################################################################
# Naturals
####################################################################################################
####################################################################################################
# Integers
####################################################################################################
####################################################################################################
# Ratios
####################################################################################################
class BREAK(t.NamedTuple): class BREAK(t.NamedTuple):
"""Abort the interpreter."""
pass pass
@ -347,10 +265,6 @@ class Module(t.NamedTuple):
return i return i
def define_function(self, name, opcodes): def define_function(self, name, opcodes):
# FIXME: This is way way WAAAAAAY too minimal. Lots of other stuff goes on a "function."
# For instance how to install handlers?
# How to consume capabilities?
try: try:
sig = FunctionRef.parse(name) sig = FunctionRef.parse(name)
assert sig.name assert sig.name
@ -364,8 +278,8 @@ class Module(t.NamedTuple):
return name return name
def define_type(self, name, signature): def define_type(self, name, signature):
# FIXME: What in TARNATION is this going to do self.types[name] = signature
pass return name
def __str__(self): def __str__(self):
b = [] b = []