Compare commits

..

2 Commits

Author SHA1 Message Date
stupidcomputer 2d64d09f24 remove some vestigial packaging stuf; redo this later 2024-06-16 19:11:23 -05:00
stupidcomputer ee93c4db4c add more tests for the ISA; ISA bugfix
added more tests to the ISA -- covers all the instructions except RST
(reset).

fixed a bug in the ISA -- when comparing two numbers, we really compared
their pointers. in C, it's the difference between

```
int a = 10;
int b = 12;

int *ap = &a;
int *bp = &b;

if (ap < bp) { /* do stuff */ }
```

the problem is that you're comparing the pointers, *not* the values they
refer to. it instead should be like

if (*ap < *bp) { /* do stuff */ }

because you need to *dereference* the value before comparing. that's
what happens in cli/data/computer.py now.
2024-06-16 19:05:58 -05:00
6 changed files with 61 additions and 137 deletions

View File

@ -1,14 +1,15 @@
# desmos-computer
## What is this?
- a client-server architecture for synchronizing a file containing Desmos expressions to a graph, (`cli/lib/server.py` and `cli/lib/clientside.py`)
- an instruction set architecture for Turing machines whose cells contain IEEE 754 compliant integers in each cell, (`cli/data/computer.py`)
- an assembler for that instruction set architecture, (not yet!)
- and other utilities. (disassembler, etc.)
- a client-server architecture for synchronizing a file containing Desmos expressions to a graph,
- a test suite for evaluating the 'correctness' of Desmos expressions,
- an instruction set architecture for Turing machines whose cells contain IEEE 754 compliant integers in each cell,
- an assembler for that instruction set architecture,
- and other utilities.
## How does the ISA work?
The 'CPU', implemented in Desmos, takes in a list (aka an array, Turing tape, etc.) and starts execution at cell 1 (lists have 1-based indexes in Desmos).
The list also serves as the memory, as well. (Think like Befunge's `p` command.)
The list also serves as the memory, as well. (Think like Befunge's `p` command.
*Todo: disconnect opcode definitions and opcodes from the actual CPU implementation. Because of this, don't rely on this table! Check the implementation in `data/computer.desmos`.*
@ -42,21 +43,12 @@ Things we're optimizing for:
In general: *embed the intelligence into the machine code, **not** the CPU/ISA!*
## Things to do
- [x] Write a test suite for the various instruction of the ISA executing *in Desmos*
- [ ] Write a test suite for evaluating arbitrary Desmos expressions and getting their expected outputs.
- [ ] Write an assembler to compile a custom Assembly language to native Desmos list format.
- [ ] Simplify all this into a command line tool.
- [x] Simplify the synchronization stack.
- [ ] Simplify the synchronization stack.
- [ ] Write documentation for all of this.
## Running tests
- Enter the nix-shell, then start a web browser.
- Navigate to `https://desmos.com/calculator`, and open the dev console
- Run `python3 -m cli sync -c` to copy the userscript to your clipboard
- Run the userscript in the console
- Run `python3 -m unittest ./cli/tests/isa.py`, or other test groups if needed
- Keep the Desmos tab focused, as it may impede the ISA testing process
## License
This project is licensed under the AGPLv3. See the `LICENSE` file for more information.

View File

@ -2,86 +2,29 @@ from .lib.server import DesmosGraphServer
from .lib.graphparser import DesmosGraph, DesmosGraphOverride
from .lib.clientside import payload as JSGraphPayload
from .data.computer import payload as ComputerPayload
from .data.testing import payload as TestingPayload
import pyperclip
import argparse
def handle_sync(parser):
if parser.copy_userscript:
pyperclip.copy(JSGraphPayload)
print("copied userscript to clipboard")
if parser.filename:
graph = DesmosGraph.from_file(parser.filename)
if parser.override:
override = DesmosGraphOverride.from_file(parser.override)
graph.include_override(override)
server = DesmosGraphServer()
server.instructions_to_run = []
server.append_inst({
"type": "insert_graph",
"graph": graph,
})
server.start(no_stop=True)
def handle_data(parser):
if parser.dataname:
if parser.dataname == "computer.desmos":
print(ComputerPayload)
elif parser.dataname == "testing.desmos":
print(TestingPayload)
return
if parser.list:
parsers = ["computer.desmos", "testing.desmos"]
print('\n'.join(parsers))
from .tests.isa import test_entry_point
def main():
parser = argparse.ArgumentParser(
prog="desmosisa",
description="a smörgåsbord of utilities for desmos, including some implementations of an desmos-based isa",
)
subparsers = parser.add_subparsers(dest="subparser_name")
sync_parser = subparsers.add_parser("sync", help="desmos calculator synchronization utilities")
sync_parser.add_argument(
'filename',
nargs='?',
help="filename of DesmosExpressions to synchronize with client"
)
sync_parser.add_argument(
'-o', '--override',
help="filename of DesmosOverride file, to override certain expressions in the DesmosExpression file",
action="store"
)
sync_parser.add_argument(
'-c', '--copy-userscript',
help="copy the userscript to the clipboard, to be pasted into the JS console within the calculator.",
action="store_true"
)
data_parser = subparsers.add_parser("data", help="access various prebuilt files")
data_parser.add_argument(
'dataname',
nargs='?',
help='name of the datafile requested'
)
data_parser.add_argument(
'-l', '--list',
help='list available datafiles',
action='store_true'
)
args = parser.parse_args()
if args.subparser_name == "sync":
handle_sync(args)
if args.subparser_name == "data":
handle_data(args)
# graph = DesmosGraph.from_file("data/computer.desmos")
# override = DesmosGraphOverride.from_file("test.override")
#
# graph.include_override(override)
# server = DesmosGraphServer()
# server.append_inst({
# "type": "insert_graph",
# "graph": graph,
# })
# server.append_inst({
# "type": "test_graph",
# "graph": graph,
# "name": "test and assert addition",
# "expectedOutput": [1, 4, 6, 0, 0, 4],
# "expression": "B",
# })
# server.start()
# print(server.outputs)
#
test_entry_point()
if __name__ == "__main__":
main()

View File

@ -22,10 +22,10 @@ id testing : B = []
: idiv(a, b, t_o) = setlistval(t_o, odiv(B[a], B[b]))
: imul(a, b, t_o) = setlistval(t_o, omul(B[a], B[b]))
: icmp(a, b, z) = { \\
B[a] = B[b] : equals -> 1 , \\
B[a] > B[b] : greater -> 1 , \\
B[a] < B[b] : less -> 1 \\
: icmp(a, b, z) = { \
B[a] = B[b] : equals -> 1 , \
B[a] > B[b] : greater -> 1 , \
B[a] < B[b] : less -> 1 \
}
: irst(a, b, c) = equals -> 0, greater -> 0, less -> 0
: ield(addr, b) = setlistval(addr, equals)
@ -63,26 +63,26 @@ id testing : B = []
: paramthree = 0
# main execution flows
: load(addr) = jumped -> 0, inst -> B[addr], \\
paramone -> B[addr + 1], \\
paramtwo -> B[addr + 2], \\
: load(addr) = jumped -> 0, inst -> B[addr], \
paramone -> B[addr + 1], \
paramtwo -> B[addr + 2], \
paramthree -> B[addr + 3]
: exec = { \\
inst = sto : isto(paramone, paramtwo), \\
inst = mov : imov(paramone, paramtwo), \\
inst = add : iadd(paramone, paramtwo, paramthree), \\
inst = cmp : icmp(paramone, paramtwo, paramthree), \\
inst = eld : ield(paramone, paramtwo), \\
inst = gld : igld(paramone, paramtwo), \\
inst = lld : illd(paramone, paramtwo), \\
inst = jmp : ijmp(paramone, paramtwo, paramthree), \\
inst = be : ibe(paramone, paramtwo, paramthree), \\
inst = bne : ibne(paramone, paramtwo, paramthree), \\
inst = bg : ibg(paramone, paramtwo, paramthree), \\
inst = bl : ibl(paramone, paramtwo, paramthree), \\
inst = sub : isub(paramone, paramtwo, paramthree), \\
inst = mul : imul(paramone, paramtwo, paramthree), \\
inst = div : idiv(paramone, paramtwo, paramthree) \\
: exec = { \
inst = sto : isto(paramone, paramtwo), \
inst = mov : imov(paramone, paramtwo), \
inst = add : iadd(paramone, paramtwo, paramthree), \
inst = cmp : icmp(paramone, paramtwo, paramthree), \
inst = eld : ield(paramone, paramtwo), \
inst = gld : igld(paramone, paramtwo), \
inst = lld : illd(paramone, paramtwo), \
inst = jmp : ijmp(paramone, paramtwo, paramthree), \
inst = be : ibe(paramone, paramtwo, paramthree), \
inst = bne : ibne(paramone, paramtwo, paramthree), \
inst = bg : ibg(paramone, paramtwo, paramthree), \
inst = bl : ibl(paramone, paramtwo, paramthree), \
inst = sub : isub(paramone, paramtwo, paramthree), \
inst = mul : imul(paramone, paramtwo, paramthree), \
inst = div : idiv(paramone, paramtwo, paramthree) \
}
: incip = {jumped = 0 : ip -> ip + instwidth[inst] + 1}

View File

@ -4,5 +4,5 @@ payload = """
: m = 3
: y = m * x + b
: y = 2m * x + b
: \\frac{x^{2+3}}{3}*4*testing
: \frac{x^{2+3}}{3}*4*testing
"""

View File

@ -11,8 +11,6 @@ function arraysEqual(a, b) {
return true;
}
var refresh = true;
function main() {
let socket = new WebSocket("ws://localhost:8764");
var toCompare = "";
@ -23,11 +21,9 @@ function main() {
}
socket.onclose = function(e) {
if (refresh) {
setTimeout(function() {
main();
}, 1000);
}
setTimeout(function() {
main();
}, 1000);
}
socket.onmessage = function(e) {
@ -87,5 +83,5 @@ function main() {
console.log(`[LOG] couldn't parse message ${e.data}`)
}
}
}
} main();
"""

View File

@ -89,25 +89,18 @@ class DesmosGraphServer:
}
)
if self.stop:
self.stop.set_result("sotp please!!!!")
self.stop.set_result("sotp please!!!!")
async def main(self, stop):
async with serve(self.ws_main, "localhost", 8764):
self.stop = stop
if not stop:
await asyncio.Future()
else:
await stop
await stop
def start(self, no_stop=False):
def start(self):
loop = asyncio.get_event_loop()
stop = loop.create_future()
if no_stop:
loop.run_until_complete(self.main(stop=None))
else:
loop.run_until_complete(self.main(stop=stop))
loop.run_until_complete(self.main(stop))
def append_inst(self, inst):
self.instructions_to_run.append(inst)