[NO TESTS] WIP
This commit is contained in:
parent
13355aeef4
commit
56b6ddd3ea
12 changed files with 264 additions and 57 deletions
|
@ -2,6 +2,8 @@ use <steel-shelving.scad>
|
||||||
use <Z4M.scad>
|
use <Z4M.scad>
|
||||||
use <tire-loft.scad>
|
use <tire-loft.scad>
|
||||||
use <printer-rack.scad>
|
use <printer-rack.scad>
|
||||||
|
use <worktop.scad>
|
||||||
|
use <worktop2.scad>
|
||||||
|
|
||||||
// Note 16" stud spacing
|
// Note 16" stud spacing
|
||||||
// Note 2.5" downgrade over run of garage; height to minimums
|
// Note 2.5" downgrade over run of garage; height to minimums
|
||||||
|
@ -136,9 +138,8 @@ translate([4, 232 - 37 - 1 - toolchest_size, 0]) {
|
||||||
|
|
||||||
//// worktop
|
//// worktop
|
||||||
let(tops=2)
|
let(tops=2)
|
||||||
translate([24 + 1, 232 - 1 - 37 - 1 - toolchest_size - 1- (48 * tops), 0]) {
|
translate([4, 232 - 1 - 37 - 1 - toolchest_size - 1- (48 * tops), 0]) {
|
||||||
rotate([0, 0, 90])
|
worktop2();
|
||||||
shelving(48 * tops, 24, 32, shelves=3);
|
|
||||||
label("Worktop", pos=[-12, (48*tops)/2, 32]);
|
label("Worktop", pos=[-12, (48*tops)/2, 32]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use <box.scad>
|
use <box.scad>
|
||||||
use <casters.scad>
|
use <casters.scad>
|
||||||
|
|
||||||
padding = 1.5;
|
function mm2in(x) = x * 0.0393701;
|
||||||
|
|
||||||
mdf_thickness = 0.75;
|
mdf_thickness = 0.75;
|
||||||
|
padding = mdf_thickness;
|
||||||
pin_inset = 3;
|
pin_inset = 3;
|
||||||
|
|
||||||
function padded(dims, padding) = [for(e=dims) e+padding];
|
function padded(dims, padding) = [for(e=dims) e+padding];
|
||||||
|
|
||||||
// dimensions for things
|
// dimensions for things
|
||||||
prusa = padded([31.5, 31.5, 35.5], padding);
|
prusa = padded([mm2in(180 * 2 + 504), mm2in(115 + 660), mm2in(910)], padding);
|
||||||
cr10 = padded([19, 27, 25], padding);
|
cr10 = padded([19, 27, 25], padding);
|
||||||
repbox = padded([19, 12.5, 12.5], padding);
|
repbox = padded([19, 12.5, 12.5], padding);
|
||||||
cart = [prusa.x, prusa.y, 6.75 + mdf_thickness];
|
cart = [prusa.x, prusa.y, 6.75 + mdf_thickness];
|
||||||
|
@ -35,14 +37,15 @@ module printer_rack() {
|
||||||
translate([0, 0, 0])
|
translate([0, 0, 0])
|
||||||
cart();
|
cart();
|
||||||
|
|
||||||
//translate([0, 0, cart.z])
|
|
||||||
//box(prusa, mdf_thickness);
|
|
||||||
|
|
||||||
translate([0, 0, cart.z])
|
translate([0, 0, cart.z])
|
||||||
|
box(prusa, mdf_thickness);
|
||||||
|
|
||||||
|
translate([0, 0, cart.z + prusa.z])
|
||||||
box([prusa.x, prusa.y, repbox.z], mdf_thickness);
|
box([prusa.x, prusa.y, repbox.z], mdf_thickness);
|
||||||
|
|
||||||
translate([0, 0, cart.z + repbox.z + mdf_thickness * 2])
|
translate([0, 0, cart.z + prusa.z + repbox.z + mdf_thickness * 2])
|
||||||
box([prusa.x, prusa.y, cr10.z], mdf_thickness);
|
box([prusa.x, prusa.y, cr10.z], mdf_thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
printer_rack();
|
printer_rack();
|
||||||
|
echo(prusa);
|
|
@ -7,5 +7,6 @@ py_project(
|
||||||
],
|
],
|
||||||
lib_deps = [
|
lib_deps = [
|
||||||
py_requirement("lark"),
|
py_requirement("lark"),
|
||||||
|
py_requirement("flask"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
5
projects/shogoth/src/python/shogoth/analyzer/__init__.py
Normal file
5
projects/shogoth/src/python/shogoth/analyzer/__init__.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""A syntax analyzer for Shogoth."""
|
||||||
|
|
||||||
|
from .impl import *
|
135
projects/shogoth/src/python/shogoth/analyzer/impl.py
Normal file
135
projects/shogoth/src/python/shogoth/analyzer/impl.py
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""The implementation of Shogoth's lexical analyzer."""
|
||||||
|
|
||||||
|
from abc import ABC
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import typing as t
|
||||||
|
|
||||||
|
from shogoth.types import List, Vec, Keyword, Symbol
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Namespace:
|
||||||
|
name: Symbol
|
||||||
|
mappings: t.Mapping[Symbol, t.Any]
|
||||||
|
|
||||||
|
def resolve(self, name: Symbol) -> t.Optional[Symbol]:
|
||||||
|
if name in self.mappings:
|
||||||
|
return name.qualify(self.name.name)
|
||||||
|
|
||||||
|
def __contains__(self, item):
|
||||||
|
return item.namespace == self.name and item.unqualified() in self.mappings
|
||||||
|
|
||||||
|
def __getitem__(self, key: Symbol):
|
||||||
|
return self.mappings[key.unqualified()]
|
||||||
|
|
||||||
|
def get(self, key: Symbol, default=None):
|
||||||
|
if key in self:
|
||||||
|
return self[key]
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
class Expr(ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConstExpr(Expr):
|
||||||
|
val: t.Any
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ListExpr(Expr):
|
||||||
|
children: t.List[t.Any]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MapExpr(Expr):
|
||||||
|
kvs: t.List[t.Tuple[t.Any, t.Any]]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InvokeExpr(Expr):
|
||||||
|
target: Expr
|
||||||
|
args: t.List[Expr]
|
||||||
|
# FIXME: kwargs/star-args?
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class IfExpr(Expr):
|
||||||
|
"""(if* test then else)"""
|
||||||
|
test: Expr
|
||||||
|
pos_branch: Expr
|
||||||
|
neg_branch: Expr
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LetExpr(Expr):
|
||||||
|
"""(let* [name binding name2 binding2] body)"""
|
||||||
|
bindings: t.List[t.Tuple[Symbol, Expr]]
|
||||||
|
body: Expr
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FnExpr(Expr):
|
||||||
|
"""(fn* args body)"""
|
||||||
|
args: t.List[Symbol]
|
||||||
|
body: Expr
|
||||||
|
|
||||||
|
|
||||||
|
BOOTSTRAP = "lang.shogoth.v0.bootstrap"
|
||||||
|
SPECIALS = Namespace(Symbol(BOOTSTRAP), {
|
||||||
|
Symbol("if*"): None,
|
||||||
|
Symbol("let*"): None,
|
||||||
|
Symbol("fn*"): None,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
GLOBALS = Namespace(Symbol("lang.shogoth.v0.core"), {
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: This is really expand... isn't it.
|
||||||
|
class Analyzer:
|
||||||
|
def __init__(self, specials, globals):
|
||||||
|
self._specials = specials
|
||||||
|
self._globals = globals
|
||||||
|
|
||||||
|
def resolve(self, module, name: Symbol):
|
||||||
|
return module.resolve(name) or self._globals.resolve(name) or self._specials.resolve(name)
|
||||||
|
|
||||||
|
def analyze(self, module: Namespace, expr: t.Any):
|
||||||
|
|
||||||
|
def _analyze(e):
|
||||||
|
return self.analyze(module, e)
|
||||||
|
|
||||||
|
if isinstance(expr, (int, float, str, Keyword)):
|
||||||
|
return ConstExpr(expr)
|
||||||
|
|
||||||
|
if isinstance(expr, Vec):
|
||||||
|
return ListExpr([self.analyze(module, e) for e in expr])
|
||||||
|
|
||||||
|
if isinstance(expr, List) and len(expr) > 1 and isinstance(expr[0], Symbol):
|
||||||
|
if (target := self.resolve(module, expr[0])):
|
||||||
|
match target:
|
||||||
|
case Symbol("if*", BOOTSTRAP):
|
||||||
|
assert len(expr) == 4
|
||||||
|
return IfExpr(_analyze(expr[1]), _analyze(expr[2]), _analyze(expr[3]))
|
||||||
|
|
||||||
|
case Symbol("let*", BOOTSTRAP):
|
||||||
|
assert len(expr) == 3
|
||||||
|
return LetExpr([(name, _analyze(e)) for name, e in expr[1]], _analyze(expr[2]))
|
||||||
|
|
||||||
|
case Symbol("fn*", BOOTSTRAP):
|
||||||
|
assert len(expr) == 3
|
||||||
|
return FnExpr(expr[1], _analyze(expr[2]))
|
||||||
|
|
||||||
|
# FIXME: Macros go here? Or is macroexpansion separate?
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return InvokeExpr(_analyze(target), [_analyze(e) for e in expr[1:]])
|
||||||
|
|
||||||
|
|
||||||
|
raise ValueError(f"Unable to analyze {expr!r} ({type(expr)})")
|
|
@ -1,6 +1,3 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from .impl import Reader
|
from .impl import *
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["Reader"]
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from typing import Any
|
||||||
|
|
||||||
from lark import Token, Tree
|
from lark import Token, Tree
|
||||||
from shogoth.parser import parse
|
from shogoth.parser import parse
|
||||||
from shogoth.types import Keyword, Symbol
|
from shogoth.types import Keyword, Symbol, List, Vec
|
||||||
|
|
||||||
|
|
||||||
# Monkeypatching for py3.10 matching
|
# Monkeypatching for py3.10 matching
|
||||||
|
@ -42,10 +42,10 @@ class Reader(object):
|
||||||
return self._read(children[0])
|
return self._read(children[0])
|
||||||
|
|
||||||
case Tree(Token("RULE", "plist"), children):
|
case Tree(Token("RULE", "plist"), children):
|
||||||
return [self._read(c) for c in children]
|
return List([self._read(c) for c in children])
|
||||||
|
|
||||||
case Tree(Token("RULE", "blist"), children):
|
case Tree(Token("RULE", "blist"), children):
|
||||||
return [self._read(c) for c in children]
|
return Vec([self._read(c) for c in children])
|
||||||
|
|
||||||
case Tree(Token("RULE", "mapping"), children):
|
case Tree(Token("RULE", "mapping"), children):
|
||||||
return dict(self._read(c) for c in children)
|
return dict(self._read(c) for c in children)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
"""A testing REPL."""
|
"""A testing REPL."""
|
||||||
|
|
||||||
|
|
||||||
from shogoth.reader import Reader
|
from shogoth.reader import Reader
|
||||||
|
from shogoth.types import Symbol
|
||||||
|
from shogoth.analyzer import Analyzer, SPECIALS, GLOBALS, Namespace
|
||||||
|
|
||||||
from prompt_toolkit import (
|
from prompt_toolkit import (
|
||||||
print_formatted_text,
|
print_formatted_text,
|
||||||
|
@ -24,12 +25,16 @@ STYLE = Style.from_dict(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
SPINNER = Spinner(["|", "/", "-", "\\"], 200)
|
SPINNER = Spinner("|/-\\", 200)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
reader = Reader()
|
reader = Reader()
|
||||||
|
analyzer = Analyzer(SPECIALS, GLOBALS)
|
||||||
|
ns = Namespace(Symbol("user"), {})
|
||||||
|
|
||||||
session = PromptSession(history=FileHistory(".shogoth.history"))
|
session = PromptSession(history=FileHistory(".shogoth.history"))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
line = session.prompt([("class:prompt", ">>> ")], style=STYLE)
|
line = session.prompt([("class:prompt", ">>> ")], style=STYLE)
|
||||||
|
@ -40,9 +45,12 @@ def main():
|
||||||
|
|
||||||
with yaspin(SPINNER):
|
with yaspin(SPINNER):
|
||||||
read = reader.read(line)
|
read = reader.read(line)
|
||||||
|
|
||||||
print(read, type(read))
|
print(read, type(read))
|
||||||
|
|
||||||
|
with yaspin(SPINNER):
|
||||||
|
expr = analyzer.analyze(ns, read)
|
||||||
|
print('analyze ]', expr, type(expr))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
26
projects/shogoth/src/python/shogoth/server/impl.py
Normal file
26
projects/shogoth/src/python/shogoth/server/impl.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""The implementation of a Shogoth evaluation server."""
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/api/v0/login", method=["POST"])
|
||||||
|
def login():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/v0/logout", method=["POST"])
|
||||||
|
def logout():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/v0/session", method=["GET"])
|
||||||
|
def get_session():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@app.route("/api/v0/session", method=["POST"])
|
||||||
|
def make_session():
|
||||||
|
pass
|
|
@ -4,37 +4,37 @@ from .keyword import Keyword
|
||||||
from .symbol import Symbol
|
from .symbol import Symbol
|
||||||
|
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from typing import NamedTuple, List, Mapping, Any
|
import typing as t
|
||||||
|
|
||||||
from uuid import UUID, uuid4
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
|
||||||
class TypeVariable(NamedTuple):
|
class TypeVariable(t.NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
id: UUID = uuid4()
|
id: UUID = uuid4()
|
||||||
|
|
||||||
|
|
||||||
class ArrayExpr(NamedTuple):
|
class ArrayExpr(t.NamedTuple):
|
||||||
child: Any
|
child: t.Any
|
||||||
|
|
||||||
|
|
||||||
class SumExpr(NamedTuple):
|
class SumExpr(t.NamedTuple):
|
||||||
children: List[Any]
|
children: t.List[t.Any]
|
||||||
|
|
||||||
|
|
||||||
class ProductExpr(NamedTuple):
|
class ProductExpr(t.NamedTuple):
|
||||||
children: Mapping[str, Any]
|
children: t.Mapping[str, t.Any]
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
|
||||||
class Function(NamedTuple):
|
class Function(t.NamedTuple):
|
||||||
"""The type of a function; a subset of its signature."""
|
"""The type of a function; a subset of its signature."""
|
||||||
|
|
||||||
|
|
||||||
class FunctionRef(NamedTuple):
|
class FunctionRef(t.NamedTuple):
|
||||||
raw: str
|
raw: str
|
||||||
type_params: list
|
type_params: list
|
||||||
name: str
|
name: str
|
||||||
|
@ -55,3 +55,18 @@ class FunctionRef(NamedTuple):
|
||||||
cls.parse_list(args),
|
cls.parse_list(args),
|
||||||
cls.parse_list(ret)
|
cls.parse_list(ret)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Closure(t.NamedTuple):
|
||||||
|
target: t.Union["Closure", FunctionRef]
|
||||||
|
args: t.List[t.Any]
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME (arrdem 2022-05-30):
|
||||||
|
# Find a better name for this
|
||||||
|
class Vec(list):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class List(list):
|
||||||
|
pass
|
||||||
|
|
|
@ -1,5 +1,21 @@
|
||||||
from typing import NamedTuple
|
import typing as t
|
||||||
|
|
||||||
|
|
||||||
class Symbol(NamedTuple):
|
class Symbol(t.NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
|
namespace: t.Optional[str] = None
|
||||||
|
|
||||||
|
def qualify(self, ns: str):
|
||||||
|
return Symbol(self.name, ns)
|
||||||
|
|
||||||
|
def unqualified(self):
|
||||||
|
if not self.namespace:
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return Symbol(self.name)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.namespace:
|
||||||
|
return f"{self.namespace}/{self.name}"
|
||||||
|
else:
|
||||||
|
return self.name
|
||||||
|
|
|
@ -127,7 +127,7 @@ class Opcode:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class CALLC(NamedTuple):
|
class CALLC(NamedTuple):
|
||||||
"""(`CLOSURE<... A, ... B>`, ... A) -> (... B)
|
"""(`CLOSURE<... A to ... B>`, ... A) -> (... B)
|
||||||
Call [closure]
|
Call [closure]
|
||||||
|
|
||||||
Make a dynamic call to the closure at the top of stack.
|
Make a dynamic call to the closure at the top of stack.
|
||||||
|
@ -139,32 +139,32 @@ class Opcode:
|
||||||
|
|
||||||
nargs: int = 0
|
nargs: int = 0
|
||||||
|
|
||||||
# ####################################################################################################
|
####################################################################################################
|
||||||
# # Structures
|
# Structures
|
||||||
# ####################################################################################################
|
####################################################################################################
|
||||||
# class STRUCT(NamedTuple):
|
class STRUCT(NamedTuple):
|
||||||
# """(*) -> (T)
|
"""(*) -> (T)
|
||||||
# Consume the top N items of the stack, producing a struct of the type `structref`.
|
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`.
|
|
||||||
# """
|
|
||||||
#
|
|
||||||
# structref: str
|
|
||||||
# nargs: int
|
|
||||||
|
|
||||||
# class FLOAD(NamedTuple):
|
The name and module path of the current function MUST match the name and module path of `structref`.
|
||||||
# """(A) -> (B)
|
"""
|
||||||
# Consume the struct reference at the top of the stack, producing the value of the referenced field.
|
|
||||||
# """
|
|
||||||
#
|
|
||||||
# fieldref: str
|
|
||||||
|
|
||||||
# class FSTORE(NamedTuple):
|
structref: str
|
||||||
# """(A) -> (B)
|
nargs: int
|
||||||
# Consume the struct reference at the top of the stack, producing the value of the referenced field.
|
|
||||||
# """
|
class FLOAD(NamedTuple):
|
||||||
#
|
"""(A) -> (B)
|
||||||
# fieldref: str
|
Consume the struct reference at the top of the stack, producing the value of the referenced field.
|
||||||
|
"""
|
||||||
|
|
||||||
|
fieldref: str
|
||||||
|
|
||||||
|
class FSTORE(NamedTuple):
|
||||||
|
"""(A) -> (B)
|
||||||
|
Consume the struct reference at the top of the stack, producing the value of the referenced field.
|
||||||
|
"""
|
||||||
|
|
||||||
|
fieldref: str
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Arrays
|
# Arrays
|
||||||
|
|
Loading…
Reference in a new issue