Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active October 28, 2025 11:51
Show Gist options
  • Select an option

  • Save kenwebb/273e045fc59c9bbb3e0880258a041dce to your computer and use it in GitHub Desktop.

Select an option

Save kenwebb/273e045fc59c9bbb3e0880258a041dce to your computer and use it in GitHub Desktop.
EC-4000 Distance Traveled
/**
* Ken Webb
* 2025 Oct 17
* EC4000 (TI57) emulation
* my very first program from 1978, redone using TypeScript
* 18 Oct - copied from rip to Lenovo
* 19 Oct - and then copied to RPi4
* 21 Oct - edited at meetup
*
* TODO
* - add more TODOs for Tuesday
* - deal with display value, getNextDisplay()
* - PARTLY DONE handle combining separate digits [0..9] and "." into strings and/or integers
* - digits()
* - I can collect the digits into a string
* - BUT how do I use this collection of digits as a number in a numeric expression such as 123+456 ?
* - 123+456=
* - each number is bracketed by +-xDIV=COS etc.
* - maybe I should accumulate the digits in the display variable (or other place) where the next instruction wlll naturally look for a number ?
* - maybe put each complete number onto a stack; the problem here is infix expressions (3 + 4); s-expressions (+ 3 4) (prefix) are simpler, or reverse polish (3 4 +) (postfix)
* - TODO look for an algorithm to compute arithmetic infix expressions
* - DONE get the new monitor working
* - use enum rather than string in my switch statement
* - I have several ways of dealing with numbers/digits: OpCodes _0, zero, 0
* - OpCodes is an enum, my programs are string[] - how do I get these two to work together?
*/
enum OpCodes {
_0 = "0",
_1 = "1",
_2 = "2",
_3 = "3",
_4 = "4",
_5 = "5",
_6 = "6",
_7 = "7",
_8 = "8",
_9 = "9",
/**
* 2nd
*/
_2nd = "2nd",
/**
* LRN - "Learn" Key
* Pressing this key once, puts calculator in "learn" mode — ready to remember up to 50 program steps (numbered 00 to 49).
* Display switches to special format: 00 00.
* Pressing this key once again takes calculator out of learn mode, calculator retains program steps.
* (Display reverts to the standard format).
*/
LRN = "LRN",
/**
* RST - Reset Key
* Resets program pointer to first step (step 00), whether entered from the keyboard or encountered as part of a program.
* (Also, clears Subroutine Return register.)
*/
RST = "RST",
/**
* STO n - (n from 0 to 7) stores the number in the display in the memory you select (0 to 7).
*/
STO = "STO",
/**
* RCL n - recalls the number from memory n into the display.
*/
RCL = "RCL",
/**
*
*/
SUM = "SUM",
/**
* (
*/
//_(, // how do I represent this character? https://en.wikipedia.org/wiki/Bracket U+0028 ( LEFT PARENTHESIS (()
LPAR = "(",
/**
* )
*/
//_), // how do I represent this character? U+0029 ) RIGHT PARENTHESIS ())
RPAR = ")",
/**
* X - +
*/
DIV = "DIV",
/**
* GTO - GOTO label
* n _ Go to Label n Key Sequence.
* Causes program pointer to immediately go to label n (n from 0 to 9),
* whether encountered as part of a program, or used from the keyboard.
* GT0 [2nd] nn — Go to Step Number nn Key Sequence (nn from 00 to 49)
* May be used when out of learn mode only. Positions program pointer at step number nn.
*/
GTO = "GTO",
TIMES = "X",
MINUS = "-",
PLUS = "+",
/**
* R/S — Run/Stop Key
* When out of learn mode, this is the start/stop key for your program.
* If the program is stopped, pressing R/S starts it;
* if it's running, pressing R/S stops it.
* When R/S is inserted as part of a program (in learn mode) it will stop the program at that point.
*/
R_S = "R/S", // R/S
EQUALS = "=",
};
/**
* Opcodes that follow "2nd";
*/
enum OpCodes2nd {
/**
* The Pause Key Sequence.
* While a program is runninng and the program pointer comes to a 2nd Pause instruction,
* it stops the program for about 3/4 of a second and displays whatever result is in the display register at that point.
* Then, it continues on to the next step.
*/
Pause = "Pause",
/**
* The Label Key Sequence
* This key allows you to label any point in a program, or a subroutine.
* You can label up to 10 points in a program.
* @param n - any digit 0 through 9
*/
Lbl = "Lbl",
/**
* The "Decrement and Skip on Zero" Key Sequence.
*/
Dsz = "Dsz"
}
type Test = {
un: string,
deux: number
}
/**
* ip - instruction pointer, program pointer
* index into the program memory; zero-based
*/
let ip: number = 0;
/**
* display - the display on the EC4000
*/
let display: number = 0;
/**
* Get the next item from the display.
* This simulates a person having typed these.
* This function will return a different sequence for each program.
* For now, the sequence is hard-coded here.
*/
const getNextDisplay = (): number => {
display = displayArr[displayCounter++];
return display;
}
const displayArr: number[] = [3, 4];
let displayCounter: number = 0;
const test01: Test = {un: "One", deux: 2};
console.log(OpCodes);
console.log(OpCodes.STO);
console.log(OpCodes["0"]);
console.log(test01);
//let memory: Array<number> = new Array(8);
let memory = new Array(8);
memory.fill(0);
memory[0] = 17;
memory[7] = 23;
console.log(memory, typeof memory, memory.length);
/**
* first simple program from the EC-4000 manual p.9
*/
const prog01: string[] = `
LRN
X 2 =
2nd Pause
RST
LRN
RST
`.trim().split("\n");
/**
* sample program - July 27, 1978 - Distance Travelled at Constant Velocity
* A program to calculate the distance travelled at one second intervals, given time and velocity.
* (see TY Calculus p. 33)
* memory 1 - t value
* memory 2 - v value
*/
const prog02: string[] = `
LRN
STO 1
R/S
STO 2
2nd Lbl 1
RCL 1
2nd Pause
X
RCL 2
=
2nd Pause
2nd Pause
RCL 1
+
1
=
STO 1
GTO 1
LRN
RST
`.trim().split("\n");
const prog03: string[] = `
1
2
3
.
4
5
`.trim().split("\n");
/*
How to use it:
- see the steps that I wrote down in 1978
*/
console.log(`prog01[4] ${prog01[4]}`);
console.log(`prog02[4] ${prog02[4]}`);
// opCode functions
/**
* toggle Learn mode; nothing to do
*/
const lrn = (): void => {return;}
/**
* rst - reset the instruction pointer (ip)
*/
const rst = (): void => {
ip = 0; // reset the instruction pointer
return;
}
const gto = (mix: number): void => {
ip = mix;
return;
}
/**
* sto - stores the number in the display in the memory you select (0 to 7)
* @param mix - index into the memory array 0..7
*/
const sto = (mix: number): void => {
console.log(`sto: ${mix} ${display}`);
memory[mix] = display;
}
/**
* rcl - recalls the number from memory n into the display
*/
const rcl = (mix: number): void => {
display = memory[mix];
console.log(`rcl: ${mix} ${display}`);
}
// the numbers 0..9
const succ = (n: number): number => n + 1;
const zero = (): number => 0;
const one = (): number => succ(zero());
const two = (): number => succ(one());
const three = (): number => succ(two());
const four = (): number => succ(three());
const five = (): number => succ(four());
const six = (): number => succ(five());
const seven = (): number => succ(six());
const eight = (): number => succ(seven());
const nine = (): number => succ(eight());
console.log(`zero: ${zero()}`);
console.log(`eight: ${eight()}`);
// TODO these are placeholders
const plus = () => null;
const minus = () => null;
const times = () => null;
const div = () => null;
console.log(seven() * six());
// ========================================== digits
let collectedDigits = "";
/**
* digits - Handle digits in the program [0..9] and "."
* @param - digit - a digit or dot
*/
const digits = (digit: string): void => {
// TODO
collectedDigits += digit;
console.log(`digits: found ${digit}`);
}
// ========================================== end digits
/**
* Parse and execute a EC4000 program.
* @param parr - An array of EC4000 program instructions.
* @remarks
* The opcodes are ordered as presented on the EC-4000 Reference Guide (the blue folding card)
*/
const parse = (parr: string[]): void => {
parr.forEach((pinst: string): void => {
console.log("|" + pinst + "|");
const pline = pinst.trim().split(" ");
const opcode: string = pline[0];
// TODO use the enum value rather than a string
switch (opcode) {
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
digits(opcode);
break;
case "lnx": break;
case "INV": break;
case "CE": break;
case "CLR": break;
case "2nd":
parse2nd(pline.slice(1));
break;
case "x<t": break;
case "x2": break;
case "sqrx": break;
case "1/x": break;
case OpCodes.STO:
sto(Number(pline[1]));
break;
case OpCodes.RCL:
rcl(Number(pline[1]));
break;
case "SUM": break;
case "yx": break;
case "EE": break;
case "(": break;
case ")": break;
case "div": break;
case "GTO": break;
case "X": break;
case "SBR": break;
case "-": break;
case "RST":
rst();
break;
case "+": break;
case "R/S": break;
case ".":
digits(opcode);
break;
case "+/-": break;
case "=": break;
case "": break;
case "LRN": lrn(); break;
default:
console.log(`unknown opcode: ${opcode}`);
break;
}
});
}
/**
*
*/
const parse2nd = (pline: string[]): void => {
console.log("|2 " + pline.join("_") + "|");
//const pline2 = pline.trim().split(" ");
const code: string = pline[0];
switch (code) {
case "log": break;
case "C.t": break;
case "tan": break;
case "sin": break;
case "cos": break;
case "PI": break;
case "Pause": break;
case "Exc": break;
case "Prd": break;
case "Nop": break;
case "FIX": break;
case "Int": break;
case "Deg": break;
case "Dsz": break;
case "Rad": break;
case "x=t": break;
case "Grad": break;
case "Lbl": break;
//case "": break;
default: console.log(`unknown 2nd opcode: ${code}`); break;
}
}
display = 33;
console.log(`progBEFORE d ${display} m ${memory.join(" ")}`);
//parse(prog01);
//parse(prog02);
parse(prog03);
console.log(`progAFTER d ${display} m ${memory.join(" ")}`);
console.log(`collectedDigits: ${collectedDigits}`);
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Tue Oct 28 2025 07:49:11 GMT-0400 (Eastern Daylight Time)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: EC-4000 Distance Traveled
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: 273e045fc59c9bbb3e0880258a041dce
Keywords: EC-4000
My Notes
--------
2025 Oct 23
This project combines two things:
(1) In 1978 I bought a EC-4000 (TI-57) programmable calculator and wrote a bunch of simple programs.
(2) Today I am learning to code using TypeScript.
I have written a starter TypeScript program that runs in a console window using tsc and node.
The goal is to simulate the EC-4000 program in TypeScript.
In this Xholon workbook, I use the generated JavaScript code to build a more complete simulation,
and to see how I can get Xholon and TypeScript working together.
### The original 1978 EC-4000 program
LRN
STO 1
R/S
STO 2
2nd Lbl 1
RCL 1
2nd Pause
X
RCL 2
=
2nd Pause
2nd Pause
RCL 1
+
1
=
STO 1
GTO 1
LRN
RST
### References
(1) see my TypeScript program on RPi4
### TODO
- use a "working memory" variable, as equivalent to EC-4000 display
- there is only one working memory value, that's it
- data has to be moved in and out of memory (8 values)
- working <-> memory(8)
- DONE write a parser (see ref[1])
- reuse some of the code in the tsc-generated JavaScript code
- including the OpCodes (TypeScript enum, JavaScript var with properties
- BUT maybe OpCodes should be an Object in TypeScript and JavaScript ? NO for now
- DONE save the TypeScript program to the gist, as a separate file
- numbers are put together one digit at a time
- I need a way to recognize when a number is complete ?
- either it will actually work OK the way it is now, or I could have a state machine that knows if we are currently reading a number
- carefully work out all the data pathways
- draw a complete diagram
- state machine ? opCodes are the events
- is this a register machine?
- see part of book I photocopied
### Correspondences between the EC-4000 code and the Xholon implementation
- the setup part of the EC-4000 is implemented by Xholon postConfigure()
- the EC-4000 "2nd Lbl 1" ... "GTO 1" loop is implemented by Xholon act()
- GOTO label vs function with start and end
- EC-4000 STO and RCL are implemented by Xholon arrow functions sto() and rcl()
- EC-4000 R/S and 2nd Pause are like Xholon Step and Pause
- EC-4000 LRN is like Xholon DistanceTraveledbehavior coding
- it's not clear how to handle/parse EC-4000 infix operations + - × ÷ and =
-
]]></Notes>
<_-.XholonClass>
<PhysicalSystem/>
<!-- A manually generated Xholon Script that directly implements the Distance Traveled EC-4000 program. Intended for initial testing and playing around -->
<DistanceTraveled/>
<!-- Test definition of EC-4000 opcodes, based largely on what TypeScript generated from program (see ref[1]) -->
<TestOpCodes superClass="script"/>
<Ec4000Program superClass="Attribute_String"/>
<Ec4000Programs/>
<Ec4000Parser superClass="script"/>
<Setup/>
</_-.XholonClass>
<xholonClassDetails>
<DistanceTraveled><Color>green</Color></DistanceTraveled>
<Avatar><Color>orange</Color></Avatar>
<TestOpCodes><DefaultContent><![CDATA[
// the EC-4000 code parser should be able to use this
var me, OpCodes, OpCodes2nd, beh = {
postConfigure: function() {
me = this.cnode;
//me.println(me.name() + " getting OpCodes and OpCodes2nd");
OpCodes = this.getOpCodes({});
OpCodes2nd = this.getOpCodes2nd({});
// TODO
//console.log(OpCodes["("]);
//console.log(OpCodes.STO);
//console.log(OpCodes);
//me.println("Testing");
//me.println(OpCodes["("]);
//me.println(OpCodes.STO);
//me.println(OpCodes["STO"]);
//me.println(OpCodes[0]);
//me.println(OpCodes["0"]);
//me.println(OpCodes2nd["Pause"]);
},
act: function() {
// TODO
},
/* TESTING processReceivedSyncMessage
test using Dev Tools:
var tocs = temp0;
tocs.call(103, "data");
- this test works
var tocs = temp0;
var response = tocs.call(103, "data");
var rdata = response.data;
var OpCodes = rdata[0];
var OpCodes2nd = rdata[1];
//console.log(OpCodes);
//console.log(OpCodes2nd);
- this test also works!
*/
processReceivedSyncMessage(msg) {
me.println("received message sync: " + msg.signal);
console.log("received message sync: " + msg.signal);
//return "TODO return a link to OpCodes and OpCodes2nd"; // this works!
return [OpCodes, OpCodes2nd];
},
getOpCodes: function (OpCodes) {
OpCodes["0"] = "0";
OpCodes["1"] = "1";
OpCodes["2"] = "2";
OpCodes["3"] = "3";
OpCodes["4"] = "4";
OpCodes["5"] = "5";
OpCodes["6"] = "6";
OpCodes["7"] = "7";
OpCodes["8"] = "8";
OpCodes["9"] = "9";
/**
* 2nd
*/
OpCodes["2nd"] = "2nd";
/**
* LRN - "Learn" Key
* Pressing this key once, puts calculator in "learn" mode — ready to remember up to 50 program steps (numbered 00 to 49).
* Display switches to special format: 00 00.
* Pressing this key once again takes calculator out of learn mode, calculator retains program steps.
* (Display reverts to the standard format).
*/
OpCodes["LRN"] = "LRN";
/**
* RST - Reset Key
* Resets program pointer to first step (step 00), whether entered from the keyboard or encountered as part of a program.
* (Also, clears Subroutine Return register.)
*/
OpCodes["RST"] = "RST";
/**
* STO n - (n from 0 to 7) stores the number in the display in the memory you select (0 to 7).
*/
OpCodes["STO"] = "STO";
/**
* RCL n - recalls the number from memory n into the display.
*/
OpCodes["RCL"] = "RCL";
/**
*
*/
OpCodes["SUM"] = "SUM";
/**
* (
*/
//_(, // how do I represent this character? https://en.wikipedia.org/wiki/Bracket U+0028 ( LEFT PARENTHESIS (&lpar;)
OpCodes["("] = "(";
/**
* )
*/
//_), // how do I represent this character? U+0029 ) RIGHT PARENTHESIS (&rpar;)
OpCodes[")"] = ")";
/**
* X - +
*/
OpCodes["/"] = "/";
/**
* GTO - GOTO label
* n _ Go to Label n Key Sequence.
* Causes program pointer to immediately go to label n (n from 0 to 9),
* whether encountered as part of a program, or used from the keyboard.
* GT0 [2nd] nn — Go to Step Number nn Key Sequence (nn from 00 to 49)
* May be used when out of learn mode only. Positions program pointer at step number nn.
*/
OpCodes["GTO"] = "GTO";
OpCodes["X"] = "X";
OpCodes["-"] = "-";
OpCodes["+"] = "+";
/**
* R/S — Run/Stop Key
* When out of learn mode, this is the start/stop key for your program.
* If the program is stopped, pressing R/S starts it;
* if it's running, pressing R/S stops it.
* When R/S is inserted as part of a program (in learn mode) it will stop the program at that point.
*/
OpCodes["R/S"] = "R/S";
OpCodes["="] = "=";
return OpCodes;
},
//(OpCodes || (OpCodes = {}));
/**
* Opcodes that follow "2nd";
*/
//var OpCodes2nd;
getOpCodes2nd: function (OpCodes2nd) {
/**
* The Pause Key Sequence.
* While a program is runninng and the program pointer comes to a 2nd Pause instruction,
* it stops the program for about 3/4 of a second and displays whatever result is in the display register at that point.
* Then, it continues on to the next step.
*/
OpCodes2nd["Pause"] = "Pause";
/**
* The Label Key Sequence
* This key allows you to label any point in a program, or a subroutine.
* You can label up to 10 points in a program.
* @param n - any digit 0 through 9
*/
OpCodes2nd["Lbl"] = "Lbl";
/**
* The "Decrement and Skip on Zero" Key Sequence.
*/
OpCodes2nd["Dsz"] = "Dsz";
return OpCodes2nd;
}
// )(OpCodes2nd || (OpCodes2nd = {}));
} // end beh
//# sourceURL=TestOpCodes.js
]]></DefaultContent></TestOpCodes>
<Ec4000Parser><DefaultContent><![CDATA[
const TESTCASE = 1;
var me, ava, ec4000prog, linesep, OpCodes, OpCodes2nd, code, ix, memory, working, operatorStack, operandStack, beh = {
postConfigure: function() {
me = this.cnode;
console.log(me, me.parent());
ava = $wnd.xh.avatar();
ec4000prog = me.xpath(`../Ec4000Programs/Ec4000Program[${TESTCASE}]`);
linesep = ec4000prog.linesep;
if (linesep === "CRLF") {linesep = "\n";};
console.log(ec4000prog);
code = ec4000prog.text().trim().split(linesep);
ix = 0;
memory = new Array(8).fill(0); // memory slots are indexed from 0 to 7;
working = {};
working.sval = ""; // accumulating String value
working.nval = 0; // numeric value
operatorStack = []; // use push and pop + - X div
operandStack = []; // use push and pop 123.456 etc.
let testOpCodes = me.xpath("../TestOpCodes");
//console.log(testOpCodes.name(), testOpCodes); // OK
var response = testOpCodes.call(103, "data");
//console.log(response);
var rdata = response.data;
//console.log(rdata);
if (rdata) {
OpCodes = rdata[0];
OpCodes2nd = rdata[1];
console.log(OpCodes);
console.log(OpCodes2nd);
}
},
act: function() {
// handle one line of EC4000 code each time step
if (ix < code.length) {
const line = code[ix].split(" ");
const opcode = line[0];
me.println(opcode + " |" + line + "|");
// TODO use the enum value rather than a string
switch (opcode) {
case OpCodes["0"]:
case OpCodes["1"]:
case OpCodes["2"]:
case OpCodes["3"]:
case OpCodes["4"]:
case OpCodes["5"]:
case OpCodes["6"]:
case OpCodes["7"]:
case OpCodes["8"]:
case OpCodes["9"]:
this.digits(opcode);
break;
case OpCodes.lnx: break;
case OpCodes.INV: break;
case OpCodes.CE: break;
case OpCodes.CLR: break;
case OpCodes["2nd"]:
this.parse2nd(line.slice(1));
break;
case OpCodes["x<t"]: break;
case OpCodes.x2: break;
case OpCodes.sqrx: break;
case OpCodes["1/x"]: break;
case OpCodes.STO: // TODO fix
this.sto(Number(line[1]), working.sval); //nval++);
break;
case OpCodes.RCL: // TODO fix
working.sval = this.rcl(Number(line[1]));
break;
case OpCodes.SUM: break;
case OpCodes.yx: break;
case OpCodes.EE: break;
case OpCodes["("]: break;
case OpCodes[")"]: break;
case OpCodes["/"]:
operatorStack.push(opcode);
operandStack.push(working.sval);
working.sval = "";
break;
case OpCodes.GTO: break;
case OpCodes.X:
operatorStack.push(opcode);
operandStack.push(working.sval);
working.sval = "";
break;
case OpCodes.SBR: break;
case OpCodes["-"]:
operatorStack.push(opcode);
operandStack.push(working.sval);
working.sval = "";
break;
case OpCodes.RST:
this.rst();
break;
case OpCodes["+"]:
operatorStack.push(opcode);
operandStack.push(working.sval);
working.sval = "";
break;
case OpCodes["R/S"]:
this.pause();
break;
case ".":
this.decimalPoint(opcode);
break;
case OpCodes["+/-"]: break;
case OpCodes["="]:
this.equals();
break;
case "": break; // ignore blank lines
case OpCodes.LRN:
this.lrn();
break;
default:
console.log(`unknown opcode: ${opcode}`);
me.println(`unknown opcode: ${opcode}`);
break;
} // end switch
} // end if
ix++;
me.println(memory);
}, // end act()
parse2nd: function(pline) {
console.log("|2 " + pline.join("_") + "|");
//const pline2 = pline.trim().split(" ");
const code = pline[0];
switch (code) {
case OpCodes2nd.log: break;
case OpCodes2nd["C.t"]: break;
case OpCodes2nd.tan: break;
case OpCodes2nd.sin: break;
case OpCodes2nd.cos: break;
case OpCodes2nd.PI: break;
case OpCodes2nd.Pause:
this.pause();
break;
case OpCodes2nd.Exc: break;
case OpCodes2nd.Prd: break;
case OpCodes2nd.Nop: break;
case OpCodes2nd.FIX: break;
case OpCodes2nd.Int: break;
case OpCodes2nd.Deg: break;
case OpCodes2nd.Dsz: break;
case OpCodes2nd.Rad: break;
case OpCodes2nd["x=t"]: break;
case OpCodes2nd.Grad: break;
case OpCodes2nd.Lbl: break;
//case "": break;
default:
console.log(`unknown 2nd opcode: ${code}`);
break;
} // end switch
}, // end parse2nd
lrn: () => null,
// ex: STO 1 this.sto(1, t)
sto: (ix, val) => memory[ix] = Number(val),
// ex: RCL 1 let t = this.rcl(1)
rcl: (ix) => memory[ix],
rst: () => {
ix = 0;
memory.fill(0);
ava.action("break"); // pause until hit p key
},
pause: () => {
ava.action("break")
},
// UNABLE TO USE THE FOLLOWING 5 FUNCTIONS
plus: function(a, b) {
return a + b;
},
minus: (a, b) => a - b,
times: (a, b) => a * b,
div: (a, b) => a / b,
digits: (val) => {
working.sval += val;
me.println(`working ${working.sval}`);
return;
},
decimalPoint: () => {
working.sval += ".";
return;
},
equals: () => {
me.println(`operatorStack ${operatorStack}`);
me.println(`operandStack ${operandStack}`);
const operator = operatorStack.pop();
const operand1 = operandStack.pop();
working.nval = Number(working.sval);
working.sval = "";
me.println(`working ${working.nval}`);
me.print(`${operand1} ${operator} ${working.nval} = `);
switch (operator) {
//case "+": me.println(plus(Number(operand1), working.nval)); break; plus or this.plus fail
case "+": me.println(Number(operand1) + working.nval); break;
case "-": me.println(Number(operand1) - working.nval); break;
case "X": me.println(Number(operand1) * working.nval); break;
case "/": me.println(Number(operand1) / working.nval); break;
default: break;
}
if (operator) {
working.nval = 0; // ??? works for some test cases, and not with others (test case 1)
}
return;
}
} // end beh
//# sourceURL=Ec4000Parser.js
]]></DefaultContent></Ec4000Parser>
</xholonClassDetails>
<PhysicalSystem>
<Setup/>
<!--
Distance Traveled
@param time0 - the time interval at time 0
@param velocity0 - the velocity at time 0 (constant velocity)
-->
<!--<DistanceTraveled time0="1" velocity0="13"/>-->
<!-- this node must come before TestOpCodes -->
<Ec4000Parser/>
<!--
Test Op Codes
-->
<TestOpCodes/>
<!-- TODO put all instances of Ec4000Program inside this container -->
<Ec4000Programs>
<!--1 this works! -->
<Ec4000Program linesep="CRLF"><![CDATA[
0
STO 0
1
1
=
STO 1
2
.
2
=
STO 2
3
=
STO 3
4
4
.
4
4
=
STO 4
5
=
STO 5
6
6
6
=
STO 6
7
=
STO 7
RST
]]></Ec4000Program>
<!--2 7 + 4 add two numbers with + works! -->
<Ec4000Program linesep="|">7|+|4|=</Ec4000Program>
<!--3 11 + 22 remember: each digit must be on its own line works! -->
<Ec4000Program linesep="|">1|1|+|2|2|=</Ec4000Program>
<!--4 works! -->
<Ec4000Program linesep="|">1|.|1|+|3|.|4|5|=</Ec4000Program>
<!--5 split this so that each character is on it's own line works! -->
<Ec4000Program linesep="">1.1+3.46=</Ec4000Program>
<!--6 works! -->
<Ec4000Program linesep="CRLF"><![CDATA[
5
X
4
=
]]></Ec4000Program>
<!--7 I added additional digits to test 123; the original content is just 1 sort-of works! -->
<Ec4000Program linesep="CRLF">
LRN
STO 1
R/S
STO 2
2nd Lbl 1
RCL 1
2nd Pause
X
RCL 2
=
2nd Pause
2nd Pause
RCL 1
+
1
2
3
=
STO 1
GTO 1
LRN
RST
</Ec4000Program>
<!--8 works! -->
<Ec4000Program linesep="CRLF">
1
4
.
2
5
+
2
3
=
</Ec4000Program>
<!--9 -->
<Ec4000Program linesep="CRLF"><![CDATA[
8
STO 0
9
STO 1
RCL 1
-
RCL 0
=
R/S
]]></Ec4000Program>
</Ec4000Programs>
</PhysicalSystem>
<DistanceTraveledbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, memory, working, beh = {
postConfigure: function() {
me = this.cnode.parent();
memory = new Array(8).fill(0); // memory slots are indexed from 0 to 7; here I need two slots with index 1 and 2; index 0 is unused
//memory[1] = Number(me.time0); // STO 1 store a value in memory[1] t (time unit in seconds)
//memory[2] = Number(me.velocity0); // STO 2 store a value in memory[2] v (velocity)
this.sto(1, me.time0);
this.sto(2, me.velocity0);
//me.println(`${memory.length} ${memory}`);
working = 0; // working memory
$wnd.xh.root().append(this.cnode.remove());
},
// TODO use working+memory, rather than t v d variables
act: function() {
//me.print(me.xhc().name() + " ");
// 2nd Lbl 1
// CALCULATE DISTANCE
//let t = this.rcl(1); //memory[1]; // RCL 1
//let v = this.rcl(2); //memory[2]; // RCL 2
//let d = v * t; // distance X
//me.println(d);
working = this.rcl(1);
//me.println(this.times(working, this.rcl(2)));
// INCREMENT TIME
//t = t + 1; // RCL 1 + 1
//this.sto(1, t); //memory[1] = t; // STO 1
this.sto(1, this.rcl(1) + 1); // do it all in one JavaScript step
// GTO 1
},
// ex: STO 1 this.sto(1, t)
sto: (ix, val) => memory[ix] = Number(val),
// ex: RCL 1 let t = this.rcl(1)
rcl: (ix) => memory[ix],
plus: (a, b) => a + b,
minus: (a, b) => a - b,
times: (a, b) => a * b,
div: (a, b) => a / b
}
//# sourceURL=DistanceTraveledbehavior.js
]]></DistanceTraveledbehavior>
<Setupbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
//$wnd.xh.root().println("SETUP " + $wnd.xh.param("TimeStepInterval"));
$wnd.xh.param("TimeStepInterval", "750");
//$wnd.xh.root().println("SETUP " + $wnd.xh.param("TimeStepInterval"));
//# sourceURL=Setupbehavior.js
]]></Setupbehavior>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>DistanceTraveled</title>
<rect id="PhysicalSystem/DistanceTraveled" fill="#98FB98" height="50" width="50" x="25" y="0"/>
<g>
<title>DistanceTraveled</title>
<rect id="PhysicalSystem/DistanceTraveled" fill="#6AB06A" height="50" width="10" x="80" y="0"/>
</g>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment