SlideShare une entreprise Scribd logo
1  sur  127
Télécharger pour lire hors ligne
1
Eleanor McHugh
co-founder @ InIdSol
https://inidsol.uk
https://shayk.online
x://@feyeleanor
leanpub://GoNotebook
slideshare://feyeleanor
linkedin://in/eleanormchugh
putting the R! in
R&D
Rough Cut
2
solving puzzles the hard way
Elric sent his mind into twisting tunnels of logic, across
endless plains of ideas, through mountains of symbolism and
endless universes of alternate truths; he sent his mind out
further and further and as it went he sent with it the words
[...] words that few of his contemporaries would
understand...
- Elric of Melniboné, Michael Moorcock
3
solving puzzles the hard way:
the ratio of squares
inscribe a circle inside a square ao
the circle touches the sides at their midpoint
inscribe a square ai inside the circle
its vertices touch the circumference
ai
ao
4
2r
2πr
2r
ai
ao
solving puzzles the hard way:
the ratio of squares
we know a lot about circles
their diameter is twice their radius r
and their circumference is 2πr
5
y
πd
d
x
ai = (2y)2
ao = d2
ai
ao
solving puzzles the hard way:
the ratio of squares
and we know a lot about squares
such as their area being the square of the
length of one side
this allows us to express the areas of the
two squares in terms of d and y
6
y
πd
d
x
ai = 4y2
ao = d2
ai
ao
solving puzzles the hard way:
the ratio of squares
7
y
πd
d
x
ai = 4y2
ao = (2x + 2y)2
ai
ao
solving puzzles the hard way:
the ratio of squares
8
y
πd
d
x
ai = 4y2
ao = 4x2 + 8xy + 4y2
ai
ao
solving puzzles the hard way:
the ratio of squares
9
y
πd
d
x
ai = 4y2
ao = 4x2 + 8xy + 4y2
ai
ao
solving puzzles the hard way:
the ratio of squares
note that the calculation of ao includes ai
which is interesting but not directly helpful in
calculating the ratio of ao to ai
however this still leaves us to figure out both
x and y which isn't particularly useful
10
y
πd
d
x
ai
ao
solving puzzles the hard way:
the ratio of squares
however we can reframe this problem
if we bisect ai along the line formed by
opposing vertices we find that this has
shares the length d - the circle diameter
d
11
y
πd
d
x
h2 = o2 + a2
d2 = (2y)2 + (2y)2
ai
ao
solving puzzles the hard way:
the ratio of squares
and by applying the pythagorean theorem
we can calculate d in terms of y
d
12
y
πd
d
x
h2 = o2 + a2
d2 = 4y2 + 4y2
ai
ao
solving puzzles the hard way:
the ratio of squares
d
13
y
πd
d
x
h2 = o2 + a2
d2 = 8y2
ai
ao
solving puzzles the hard way:
the ratio of squares
d
14
y
πd
d
x
ao = 8y2
ai = (2y)2
ai
ao
solving puzzles the hard way:
the ratio of squares
d
15
y
πd
d
x
ao = 8y2
ai = 4y2
ai
ao
solving puzzles the hard way:
the ratio of squares
d
16
y
πd
d
x
ao : ai = 8 : 4
ao : ai = 2 : 1
ai
ao
solving puzzles the hard way:
the ratio of squares
so ao is twice the area of ai
d
17
*blink*
A clever person solves a problem.
A wise person avoids it.
- Albert Einstein
18
*blink*:
the ratio of squares
algebra is a rational tool that can solve many
problems by brute force
however when you study a problem domain
in depth you start to develop intuitions -
ways of identifying shortcuts to the answer
you're after
ai
ao
d
19
*blink*:
the ratio of squares
algebra is a rational tool that can solve many
problems by brute force
however when you study a problem domain
in depth you start to develop intuitions -
ways of identifying shortcuts to the answer
you're after
ai
ao
d
20
*blink*:
the ratio of squares
if in this case we rotate ai by 45°
ao
ai d
21
*blink*:
the ratio of squares
we can see that the area of ao must be twice
the area of ai
ao
ai
22
*blink*:
the ratio of squares
a
y
y
d 2 2
Y 6 842
I s d from
d 2 24
g
a
e
12 4 2
84 442
v
using
8112 4 2
84 442
Sino
I 242 42 2 4 42
x 2 4 42 0
Cos
ay
Sino sin450
sin450
tano
Ia
seco
ha I E ai y
coseco
to ay de di 442
14472 242
12 8,2
do de
90 8 2
Sin
II
do
Cos
450
I g 2
tan450 1
sin900 1
Cos
900 0
tango
undefined
23
common sense is wrong
24
1977 1978 1979 1980
1981 1982 1983 1984
1985 1986 1987 1988
1989 1990
applied physics,
microelectronics,
& computing
1991 1992
1993 1994 1995 1996
1997 1998 1999 2000
2001 2002 2003 2004
25
● for a particle with few
degrees of freedom, its
position x and its
momentum p cannot
both be determined at
the same time
● Schrödinger's cat sums
up the weirdness of this
Uncertain Quanta
Heisenberg
Schrödinger
26
● at the smallest scale
things behave as if
distance doesn't exist
● at the largest scale
nothing can move faster
then the speed of light
● which is more true?
● wormholes!
● time travel!
● (and conspiracies!!!)
Locality & The Real
Bell
Einstein, Rosen, Podolsky
27
Incomplete Mathematics
see https://www.quantamagazine.org/how-godels-proof-works-20200714/
● Gödel vs formal methods
● any formal system able
to do elementary
arithmetic is either
inconsistent or
incomplete
● any formal system able
to express its own
consistency can prove its
own consistency if and
only if it is inconsistent
Whitehead & Russell
Gödel
28
Incomplete Mathematics
see https://www.quantamagazine.org/how-godels-proof-works-20200714/
● Gödel vs formal methods
● any formal system able
to do elementary
arithmetic is either
inconsistent or
incomplete
● any formal system able
to express its own
consistency can prove its
own consistency if and
only if it is inconsistent
29
● Turing-Church
● robot reads infinite tape
● applies rules that can
overwrite the tape then
moves the tape one
step left or right
● can compute anything
which can be computed
● physical analogue of
the Lambda Calculus
Universal Machines
The input value to be bound
to the argument x
Substitute the value into the body
The body becomes the return value
λ x . x
( ) 2
λ 2 . x
( )
λ 2 . 2
( )
2
Turing
Church
30
● the study of causal
processes and
feedback loops
● these loops regulate or
control the operation of
a system
● feedback can be
positive or negative
● used to steer a system
towards desired goals
Cybernetic Noise
31
● entropy describes the
information contained in
a system
● the higher the entropy,
the more information
that can be contained
● applications in
cryptography and
telecommunications
Information Overload
32
Loose Lips Save Ships
● Bletchley Park GC&CS
● traffic analysis
● Enigma and the Turing
electro-mechanical
bombe
● Lorenz stream cipher
and Colossus, the
world's first electronic
programmable
computer
Flowers
33
● the Memex, an electro-
mechanical platform for
managing deeply
interlinked knowledge
● Project Xanadu a
platform for publishing
hypertext & hypermedia
● WWW adds typesetting
and programmability to
hypertext
Webs of Meaning
Ted Nelson
Berners-Lee
34
● algorithms are tractable
to rigorous analysis
● Big O notation - how
long an algorithm runs
● or how much memory
an algorithm uses
● O(logx n)
● O(nx)
● O(n!)
Beyond the Machine
in programming, simplicity and
clarity ... are not a dispensable luxury,
but a crucial matter that decides
between success and failure
Dijkstra
Knuth
35
● falsifiability as the test
of empirical study
● constructivism - the
pursuit of knowledge is
shaped by social
factors
● the methods of one
paradigm do not
necessarily translate
into another paradigm
All Life is Problem Solving
In so far as a scientific statement speaks about
reality, it must be falsifiable; and in so far as it is
not falsifiable it does not speak about reality
Kuhn
Popper
36
that first deep-dive into insanity
Love is the ghost haunting your head
Love is the killer you thought was your friend
Love is the creature who lives in the dark
Sneaks up, will stick you
And painfully pick you apart
- The Beast, Concrete Blonde
37
38
39
40
41
● stack-based
● programs compose
word definitions from a
threaded dictionary
● limited type system
● ASM versions are great
for embedded systems
● Open Firmware
● gforth
● Factor (functional)
Forth
5 2 3 56 76 23 65 .s <7> 5 2 3 56 76 23 65 ok
5 4 + . 9 ok
13 2 / . 6 ok
13 2 mod . 1 ok
3 dup - . 0 ok
2 5 swap / . 2 ok
6 4 5 rot .s <3> 4 5 6 ok
4 0 drop 2 / . 2 ok
1 2 3 nip .s <2> 1 3 ok
: square ( n -- n ) dup * ; ok
5 square . 25 ok
see square : square dup * ; ok
42 42 = . -1 ok
12 53 = . 0 ok
: ?>64 dup 64 > if ." More than" else ." Less than" then ." 64!" ; ok
100 ?>64 More than 64! ok
20 ?>64 Less than 64! ok
: squares ( n -- ) 1 do i square loop ; ok
5 squares .s <4> 1 4 9 16 ok
: threes ( n n -- ) ?do i . 3 +loop ; ok
15 0 threes 0 3 6 9 12 ok
0 0 threes ok
variable age ok
21 age ! ok
age @ . 21 ok
age ? 21 ok
100 constant WATER-BOILING-POINT ok
WATER-BOILING-POINT . 100 ok
variable num-array 2 cells allot ok
num-array 3 cells erase ok
num-array 3 cells 0 fill ok
create num-array 64 , 9001 , 1337 , ok
0 cells num-array + ? 64 ok
1 cells num-array + ? 9001 ok
: of-arr ( n n -- n ) cells + ; ok
num-array 2 of-arr ? 1337 ok
20 num-array 1 of-arr ! ok
num-array 1 of-arr ? 20 ok
: i-from-rstack ( -- ) 4 0 do r@ . loop ; ok
i-from-rstack 0 1 2 3 ok
5 6 4 >r swap r> .s 6 5 4 ok
5 6 4 clearstack ok
bye
42
see https://learnxinyminutes.com/docs/forth/
5 2 3 56 76 23 65 .s
<7> 5 2 3 56 76 23 65 ok
5 4 + .
9 ok
13 2 / .
6 ok
13 2 mod .
1 ok
3 dup .s cr - .
<2> 3 3
0 ok
43
2 5 swap .s
<2> 5 2 ok
6 4 5 rot .
<3> 4 5 6 ok
4 0 drop 2 / .
2 ok
1 2 3 nip .s
<2> 1 3 ok
4 5 6 clearstack .s
<0> ok
44
: square ( n -- n ) dup * ;
ok
5 square .
25 ok
see square
: square dup * ; ok
45
: print-result . cr .s ;
12 42 42 42 = print-result cr = print-result
-1
<2> 12 42
0
<0> ok
: ?>64
dup 64 >
if ." More than"
else ." Less than"
then ." 64!" ;
100 ?>64
More than 64! ok
20 ?>64
Less than 64! ok
46
: squares ( n -- ) 1 do i square loop ;
5 .s .cr squares .s
<1> 5
<4> 1 4 9 16 ok
: threes ( n n -- ) ?do i 3 +loop ;
: reverse-stack ( n*x -- n*x') depth 1 do i roll loop ;
: print-stack ( n -- ) depth 0 do . cr loop ;
15 0 threes cr .s cr reverse-stack .s cr print-stack
<5> 0 3 6 9 12 ok
<5> 12 9 6 3 0 ok
0
3
6
9
12
ok
0 0 threes
ok
47
variable age
ok
21 age !
ok
age @ .
21 ok
age ?
21 ok
48
variable multiplier
: multiples ( n n -- )
?do
i multiplier @
+loop ;
3 multiplier ! 20 0 multiples cr .s cr reverse-stack .s
<7> 0 3 6 9 12 15 18
<7> 18 15 12 9 6 3 0 ok
2 multiplier ! 20 0 multiples cr .s cr reverse-stack .s
<10> 2 4 6 8 10 12 14 16 18
<10> 16 14 12 10 8 6 4 2 0 ok
4 multiplier ! 20 0 multiples cr .s cr reverse-stack .s
<5> 0 4 8 12 16
<5> 16 12 8 4 0 ok
49
: multiples ( n n -- )
?do
i MULTIPLIER
+loop ;
:1: Undefined word
: multiples ( n n -- ) ?do i >>>MULTIPLIER<<< +loop ;
Backtrace:
$105349A20 throw
$10535FC48 no.extensions
$10534D358 compiler-notfound1
3 constant MULTIPLIER
20 0 multiples cr .s cr reverse-stack .s
<7> 0 3 6 9 12 15 18
<7> 18 15 12 9 6 3 0 ok
4 constant MULTIPLIER redefined MULTIPLIER ok
20 0 multiples cr .s cr reverse-stack .s
<7> 0 3 6 9 12 15 18
<7> 18 15 12 9 6 3 0 ok
50
variable num-array 2 cells allot
ok
num-array 3 cells erase
num-array 3 cells 0 fill
ok
create num-array 64 , 9001 , 1337 ,
ok
0 cells num-array + ?
64 ok
1 cells num-array + ?
9001 ok
51
: of-arr ( n n -- n ) cells + ;
create num-array 64 , 9001 , 1337 ,
num-array 2 of-arr ?
1337 ok
20 num-array 2 of-arr !
ok
num-array 2 of-arr ?
20 ok
52
: i-from-rstack ( -- ) 4 0 do r@ . loop ;
i-from-rstack
0 1 2 3 ok
5 6 4 cr .s cr >r .s cr r@ . cr swap .s cr r> .s
<3> 5 6 4
<2> 5 6
4
<2> 6 5
<3> 6 5 4 ok
53
54
● tokenised interpreter
● running on Zilog Z80
● unstructured code with
GOTO and GOSUB
● no UDTs
● simple line editor
● painfully slow execution
● if you can code in this
you can probably code
in anything
Locomotive BASIC
1 REM ******************
2 REM * Amstrad Forth *
3 REM * by *
4 REM * Stephen Devine *
5 REM ******************
6 REM
10 REM (c) Computing with the Amstrad
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
250 REM Input Commands
260 w$="":er=0:LINE INPUT ln$:IF ln$="" THEN 690 ELSE IF LEN(ln$)>240 THEN PRINT"Line too
long":GOTO 260
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":G$
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
55
https://www.cpcwiki.eu/index.php/CWTA_Issue_17_-_May_1986_-_Type-Ins
Used under Fair Use for purpose of review and critique
56
1 REM ******************
2 REM * Amstrad Forth *
3 REM * by *
4 REM * Stephen Devine *
5 REM ******************
6 REM
10 REM (c) Computing with the Amstrad
100 REM Initialisation
250 REM Input Commands
680 REM Error Routine
710 REM Compile New Word
750 REM Execute Commands
1080 REM Command List
1690 REM Process Editing Commands
2540 REM Data for Core Words
Outer Interpreter (tokeniser & parser)
Word Compiler (adds entry to dictionary)
Inner Interpreter (invoke entries from dictionary)
Implemented Primitives
Implementation extension words
Primitive tokens and stack behaviour
57
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
58
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
59
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
60
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
61
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
62
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
63
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
64
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
65
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
66
100 REM Initialisation
110 MODE 2:BORDER 13:INK 1,0:INK 0,13
120 forth$=CHR$(12)+"Fred Forth V1.1"
130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT
140 temp=0:DEFINT a-z
150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40)
160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack"
170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack
Full":er$(7)="Return Stack Full"
180 spmax=100:DIM s(spmax):sp=-1
190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1)
200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT
210 cvoc$(5)="."+CHR$(34)
220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax)
230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0)
240 ON ERROR GOTO 2530
2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690
2540 REM Data for Core Words
2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/
MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1
2560 DATA
"=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1
2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1
2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1
2590 DATA
"WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2,
-2,"LOOP",0,0,"I",0,+1
2600 REM Data for Amstrad Words
2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2
2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
67
outer interpreter
68
250 REM Input Commands
260 w$="":er=0:LINE INPUT ln$:IF ln$="" THEN 690 ELSE IF LEN(ln$)>240 THEN PRINT"Line too
long":GOTO 260
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
680 REM Error Routine
690 IF POS(#0)>1 THEN PRINT CHR$(32);
700 PRINT w$;er$(er):GOTO 260
69
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
produce token stream
70
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
look for extension words
71
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
outer interpreter loop
72
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
word definition to compile
73
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
execute "byte code" or add to dictionary
check for user defined word
check for user defined variable
must be a number
"byte code" generated for token
74
270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690
280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND
290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB
1700:IF er THEN 260 ELSE w$="":GOTO 690
300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0
310 WHILE q<LEN(ln$)
320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND
330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE
PRINT"Bad definition":GOTO 260
340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400
350 IF comp THEN IF wn=0 THEN er=3:GOTO 690
360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640
380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260
390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640
400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440
410 IF comp THEN IF wn=0 THEN er=3:GOTO 690
420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690
430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640
440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480
450 IF comp THEN IF wn=0 THEN er=3:GOTO 690
460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690
470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640
480 FOR i=1 TO LEN(w$)
490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510
500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560
510 NEXT i
520 IF comp AND wn=0 THEN er=5:GOTO 690
530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690
540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260
550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640
560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590
570 IF comp AND w$=w$(1) THEN er=3:GOTO 690
580 x$=x$+w$+CHR$(4):GOTO 640
590 IF w$<>";" THEN 610
600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640
610 IF comp THEN IF wn=0 THEN 640
620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640
630 er=5:GOTO 690
640 wn=wn+1:w$(wn)=w$
650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND
660 WEND
670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760
add "byte code" for primitive
add "byte code" for user defined word
add "byte code" for user defined variable
add "byte code" for number
compiler mode sanity checks
75
compiler
76
710 REM Compile New Word
720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260
730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$
740 w$="":GOTO 690
77
710 REM Compile New Word
720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260
730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$
740 w$="":GOTO 690
78
710 REM Compile New Word
720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260
730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$
740 w$="":GOTO 690
79
inner interpreter
80
750 REM Execute Commands
760 ln=0:w$(ln)=x$:er=0
770 GOSUB 780:w$="":GOTO 690
780 p(ln)=1:ff(ln)=0:df(ln)=0
790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13)
800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1
810 IF class<>0 THEN 920
820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860
840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1
850 GOTO 1060
860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070
870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070
880 sp=sp+dsp(word,1)
890 IF word <43 THEN ON word+1 GOSUB
1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290
,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149
0,1500,1510,1520
900 IF word>42 THEN ON word-42 GOSUB
1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680
910 IF er=0 THEN 1060 ELSE 1070
920 IF class<>1 THEN 970
930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
940 IF ff(ln) THEN 1060
950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN
960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN
970 IF class<>2 THEN 1010
980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
990 IF ff(ln) THEN 1060
1000 sp=sp+1:s(sp)=@var(word):GOTO 1060
1010 IF class<>3 THEN er=1:GOTO 1070
1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND
1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1
1040 IF ff(ln) THEN 1060
1050 sp=sp+1:s(sp)=v
1060 WEND
1070 ln=ln-1:RETURN
81
750 REM Execute Commands
760 ln=0:w$(ln)=x$:er=0
770 GOSUB 780:w$="":GOTO 690
780 p(ln)=1:ff(ln)=0:df(ln)=0
790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13)
800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1
810 IF class<>0 THEN 920
820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860
840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1
850 GOTO 1060
860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070
870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070
880 sp=sp+dsp(word,1)
890 IF word <43 THEN ON word+1 GOSUB
1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290
,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149
0,1500,1510,1520
900 IF word>42 THEN ON word-42 GOSUB
1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680
910 IF er=0 THEN 1060 ELSE 1070
920 IF class<>1 THEN 970
930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
940 IF ff(ln) THEN 1060
950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN
960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN
970 IF class<>2 THEN 1010
980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
990 IF ff(ln) THEN 1060
1000 sp=sp+1:s(sp)=@var(word):GOTO 1060
1010 IF class<>3 THEN er=1:GOTO 1070
1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND
1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1
1040 IF ff(ln) THEN 1060
1050 sp=sp+1:s(sp)=v
1060 WEND
1070 ln=ln-1:RETURN
these are our execution classes
0 = primitives
1 = user defined word
2 = user defined variable
3 = numbers
82
750 REM Execute Commands
760 ln=0:w$(ln)=x$:er=0
770 GOSUB 780:w$="":GOTO 690
780 p(ln)=1:ff(ln)=0:df(ln)=0
790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13)
800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1
810 IF class<>0 THEN 920
820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860
840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1
850 GOTO 1060
860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070
870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070
880 sp=sp+dsp(word,1)
890 IF word <43 THEN ON word+1 GOSUB
1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290
,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149
0,1500,1510,1520
900 IF word>42 THEN ON word-42 GOSUB
1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680
910 IF er=0 THEN 1060 ELSE 1070
920 IF class<>1 THEN 970
930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
940 IF ff(ln) THEN 1060
950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN
960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN
970 IF class<>2 THEN 1010
980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1
990 IF ff(ln) THEN 1060
1000 sp=sp+1:s(sp)=@var(word):GOTO 1060
1010 IF class<>3 THEN er=1:GOTO 1070
1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND
1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1
1040 IF ff(ln) THEN 1060
1050 sp=sp+1:s(sp)=v
1060 WEND
1070 ln=ln-1:RETURN
these are computed GOSUBs
implementing a despatch table
to BASIC for each primitive
83
1080 REM Command List
1090 temp!=s(sp+1):IF temp!<0 THEN temp!=temp!+65536
1100 POKE s(sp+2),temp!-256*INT(temp!/256):POKE s(sp+2)+1,INT(temp!/256):RETURN
1110 s(sp)=s(sp)*s(sp+1):RETURN
1120 s(sp)=s(sp)+s(sp+1):RETURN
1130 s(sp)=s(sp)-s(sp+1):RETURN
1140 PRINT s(sp+1);CHR$(8);:RETURN
1150 WHILE ASC(MID$(w$(ln),p(ln),1))<>4:PRINT MID$(w$(ln),p(ln),1);:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)
+1:RETURN
1160 s(sp)=INT(s(sp)/s(sp+1)):RETURN
1170 temp=s(sp):s(sp)=INT(s(sp-1)/s(sp)):s(sp-1)=s(sp-1)-s(sp)*temp:RETURN
1180 s(sp)=(s(sp)<0):RETURN
1190 s(sp)=(s(sp)=0):RETURN
1200 s(sp)=(s(sp)<s(sp+1)):RETURN
1210 s(sp)=(s(sp)=s(sp+1)):RETURN
1220 s(sp)=(s(sp)>s(sp+1)):RETURN
1230 temp!=PEEK(s(sp+1))+256*PEEK(s(sp+1)+1):IF temp!>32767 THEN temp!
=temp!-65536:PRINTtemp!;CHR$(8);:RETURN ELSE PRINTtemp!;CHR$(8);:RETURN
1240 temp!=PEEK(s(sp))+256*PEEK(s(sp)+1):IF temp!>32767 THEN s(sp)=temp!-65536:RETURN ELSE
s(sp)=temp!:RETURN
1250 s(sp)=ABS(s(sp)):RETURN
1260 s(sp)=s(sp) AND s(sp+1):RETURN
1270 s(sp)=PEEK(s(sp)):RETURN
1280 PRINT:RETURN
1290 RETURN
1300 s(sp)=s(sp-1):RETURN
1310 PRINTCHR$(s(sp+1));:RETURN
1320 in$=INKEY$:IF in$="" THEN 1320 ELSE s(sp)=ASC(in$):RETURN
1330 s(sp)=MAX(s(sp),s(sp+1)):RETURN
1340 s(sp)=MIN(s(sp),s(sp+1)):RETURN
1350 s(sp)=-s(sp):RETURN
1360 s(sp)=s(sp) MOD s(sp+1):RETURN
1370 s(sp)=s(sp) OR s(sp+1):RETURN
1380 s(sp)=s(sp-2):RETURN
1390 PRINT" ";:RETURN
1400 PRINT USING "&";SPACE$(s(sp+1)-256*INT(s(sp+1)/256));:RETURN
1410 temp=s(sp):s(sp)=s(sp-1):s(sp-1)=temp:RETURN
1420 vrn=vrn+1:var(vrn)=s(sp+1):WHILE ASC(MID$(w$(ln),p(ln),1))<>4:var$(vrn)=var$(vrn)+MID$(w$
(ln),p(ln),1):p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1:RETURN
1430 s(sp)=s(sp) XOR s(sp+1):RETURN
1440 beg(ln)=p(ln):RETURN
1450 IF s(sp+1)=0 THEN p(ln)=beg(ln):RETURN ELSE RETURN
1460 IF s(sp+1)<>0 THEN RETURN ELSE ff(ln)=-1:RETURN
this is why switch statements exist
and why fallthrough is superior to break!
84
that's probably more than
you ever wanted to know
about Forth or BASIC
or how I spent the 80s...
85
this social construct kills demons
86
this social construct kills demons
87
1977 1978 1979 1980
1981 1982 1983 1984
1985 1986 1987 1988
1989 1990 1991 1992
1993 1994 1995 1996
1997 1998
embedded
1999
systems
2000
2001 2002 2003 2004
the waterfall
88
up-front design
Kent Beck
89
eXtreme Programming
the birth of agile
Planning/feedback loops
Release plan
Code
Iteration plan
Acceptance test
Stand-up meeting
Pair negotiation
Unit test
Pair programming
Months
Weeks
Days
One day
Hours
Minutes
Seconds
By DonWells - Own work based on: XP-feedback.gif, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27448045
Cultural
traditions
Analysis &
synthesis
Previous
experiences
New
information
Genetic
heritage Decision
(hypothesis)
Observations Action
(test)
Unfolding
interaction
with
environment
Feedback
Feedback
Unfolding
interaction
with
environment
Act
Decide
Orient
Observe
Implicit
guidance
& control
Feed
forward
Feed Feed
forward forward
Unfolding
circumstances
Outside
information
Implicit
guidance
& control
John Boyd's OODA loop
Feedback
90
it's war out there
the OODA loop
John Boyd
Verification
and
Validation
Project
Definition
Concept of
Operations
Requirements
and
Architecture
Detailed
Design
Integration,
Test, and
Verification
System
Verification
and Validation
Operation
and
Maintenance
Project
Test and
Integration
Implementation
Implementation
Time
91
government mandated processes
the v-model
92
software considerations in airborne systems and equipment certification
RTCA DO-178B
Level Failure condition Objectives[5] Failure Rate
A Catastrophic 66 10−9/h
B Hazardous 65 10−7/h
C Major 57 10−5/h
D Minor 28 10−3/h
E No Effect 0 n/a
93
evolutionary prototyping
the boehm spiral
Plan next Phase
Develop, verify
next-level product
Determine objectives,
alternatives, constraints
Evaluate alternatives
identify, resolve risks
Cummulative
cost
Review
Commitment
partition
Risk
analysis
Risk
analysis
Risk
analysis
Prototype 1 Prototype 2 Prototype 3
Operational
Prototype
Risk
analy-
sis
Requirements plan
life-cycle plan
Develop-
ment plan
Integration
and test
plan
Concept of
operation
Simulations, models, benchmarks
Software
requirements
Requirements
validation
Software
product
design
Design validation
and verification
Detailed
design
Code
Unit
test
Integration
and test
Acceptance
test
Implementation
94
further
down
the
spiral
95
once upon a time
Romek Ellie
96
cryptography + physics = ???
we 🔬 digital identity
97
● digital identity
● messaging
● privacy
● trust
what we do
IDENTITY & TRUST IN MONITORED SPACES
THE VIRTUES OF PRIVACY BY DESIGN
Eleanor McHugh
Romek Szczesniak
98
● ruby
● bash
● macOS
● golang
● crystal
● javascript
how we do it
99
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
this is part of a proof of concept
for a digital identity system
it's part of a series of prototypes
evolved from a series of pure
BaSH scripts
all the techniques demonstrated
are applicable to any language
with either quick compilation
speed or fast interpreter launch
like golang or ruby
100
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
Fair Use Exemptions Apply
101
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
bangs allow scripts to be executable
102
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
Environment Variables
for configuration
103
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
Environment Variables
for configuration
104
#!/bin/bash
# (c) 2017 Innovative Identity Solutions Limited
# all rights reserved
# This script defines addresses for a service infrastructure baselined at $BASEPORT."
#
# Usage:"
# export BASE_SERVICE=9000"
# source infrastructure.sh"
#
PORT=$BASE_SERVICE_PORT
ADDRESS=${SERVER_ADDRESS:=localhost}
export DOMAIN_SERVICE=$PORT
export DOMAIN_ADDRESS="$ADDRESS:$DOMAIN_SERVICE"
let PORT++
export LOGGING_SERVICE=$PORT
export LOGGING_ADDRESS="$ADDRESS:$LOGGING_SERVICE"
let PORT++
export SECURE_STORE_SERVICE=$PORT
export SECURE_STORE_ADDRESS="$ADDRESS:$SECURE_STORE_SERVICE"
let PORT++
export REGISTRY_SERVICE=$PORT
export REGISTRY_ADDRESS="$ADDRESS:$REGISTRY_SERVICE"
let PORT++
export ORACLE_SERVICE=$PORT
export ORACLE_ADDRESS="$ADDRESS:$ORACLE_SERVICE"
let PORT++
export BEAR_SERVICE=$PORT
export BEAR_ADDRESS="$ADDRESS:$BEAR_SERVICE"
let PORT++
export VAL_SERVICE=$PORT
export VAL_ADDRESS="$ADDRESS:$VAL_SERVICE"
BASE_SERVICE_PORT=$DOMAIN_SERVICE
Environment Variables
for static configuration
105
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
command-line switches
for instance variables
106
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
check for missing parameters
107
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
now for some Ruby magic
108
RUBY_DIR="$ROOT_DIR/ruby"
source scripts/basics.sh
# http_requests will print headers and response body along with stack dumps
# if the env variable DEBUG_HTTP_REQUESTS exists
ruby_web_client () {
local program=$1
ruby -e "
require 'json'
require '$CLIENTS_DIR/web'
$program
"
}
http_request () {
local version=$1
local method=$2
local address=$3
local endpoint=$4
local request_body=$5
ruby_web_client "
if ENV['DEBUG_HTTP_REQUESTS']
response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
puts 'REQUEST:'
puts $request_body
$request_body
end
puts 'RESPONSE:'
response.each_header do |k, v|
puts "#{k}: #{v}"
end
puts "body: #{response.body}"
puts
else
WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
$request_body
end rescue nil
end
"
}
where we keep our ruby scripts
some handy Bash functions
109
DATA_DIR="$ROOT_DIR/data"
COMMANDS_DIR="$ROOT_DIR/commands"
MODELS_DIR="$ROOT_DIR/models"
detect_wsl () {
set -e
grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null
}
UNIX_PROCESS_STARTUP_DELAY=1
WSL_PROCESS_STARTUP_DELAY=5
if detect_wsl ; then
wait_for_process_launch () {
sleep WSL_PROCESS_STARTUP_DELAY
}
else
wait_for_process_launch () {
sleep UNIX_PROCESS_STARTUP_DELAY
}
fi
heading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.heading '$1'
"
}
subheading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.subheading '$1'
"
}
print_cic_statement() {
ruby "$COMMANDS_DIR/cic_banner.rb"
}
finished () {
heading "DONE"
}
useful directories
110
DATA_DIR="$ROOT_DIR/data"
COMMANDS_DIR="$ROOT_DIR/commands"
MODELS_DIR="$ROOT_DIR/models"
detect_wsl () {
set -e
grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null
}
UNIX_PROCESS_STARTUP_DELAY=1
WSL_PROCESS_STARTUP_DELAY=5
if detect_wsl ; then
wait_for_process_launch () {
sleep WSL_PROCESS_STARTUP_DELAY
}
else
wait_for_process_launch () {
sleep UNIX_PROCESS_STARTUP_DELAY
}
fi
heading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.heading '$1'
"
}
subheading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.subheading '$1'
"
}
print_cic_statement() {
ruby "$COMMANDS_DIR/cic_banner.rb"
}
finished () {
heading "DONE"
}
WSL can take a long time
to launch a Linux process
so we check for it and add
a longer startup delay for
our system to boot
111
DATA_DIR="$ROOT_DIR/data"
COMMANDS_DIR="$ROOT_DIR/commands"
MODELS_DIR="$ROOT_DIR/models"
detect_wsl () {
set -e
grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null
}
UNIX_PROCESS_STARTUP_DELAY=1
WSL_PROCESS_STARTUP_DELAY=5
if detect_wsl ; then
wait_for_process_launch () {
sleep WSL_PROCESS_STARTUP_DELAY
}
else
wait_for_process_launch () {
sleep UNIX_PROCESS_STARTUP_DELAY
}
fi
heading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.heading '$1'
"
}
subheading () {
ruby -e "
require '$COMMANDS_DIR/console'
Console.subheading '$1'
"
}
print_cic_statement() {
ruby "$COMMANDS_DIR/cic_banner.rb"
}
finished () {
heading "DONE"
}
each of these is a string
containing Ruby code to
be executed by the
interpreter
112
RUBY_DIR="$ROOT_DIR/ruby"
source scripts/basics.sh
# http_requests will print headers and response body along with stack dumps
# if the env variable DEBUG_HTTP_REQUESTS exists
ruby_web_client () {
local program=$1
ruby -e "
require 'json'
require '$CLIENTS_DIR/web'
$program
"
}
http_request () {
local version=$1
local method=$2
local address=$3
local endpoint=$4
local request_body=$5
ruby_web_client "
if ENV['DEBUG_HTTP_REQUESTS']
response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
puts 'REQUEST:'
puts $request_body
$request_body
end
puts 'RESPONSE:'
response.each_header do |k, v|
puts "#{k}: #{v}"
end
puts "body: #{response.body}"
puts
else
WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
$request_body
end rescue nil
end
"
}
use local to give shell function
parameters meaningful names
113
RUBY_DIR="$ROOT_DIR/ruby"
source scripts/basics.sh
# http_requests will print headers and response body along with stack dumps
# if the env variable DEBUG_HTTP_REQUESTS exists
ruby_web_client () {
local program=$1
ruby -e "
require 'json'
require '$CLIENTS_DIR/web'
$program
"
}
http_request () {
local version=$1
local method=$2
local address=$3
local endpoint=$4
local request_body=$5
ruby_web_client "
if ENV['DEBUG_HTTP_REQUESTS']
response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
puts 'REQUEST:'
puts $request_body
$request_body
end
puts 'RESPONSE:'
response.each_header do |k, v|
puts "#{k}: #{v}"
end
puts "body: #{response.body}"
puts
else
WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
$request_body
end rescue nil
end
"
}
shell variables are strings
this allows us to pass in a
ruby program as a string
which will then be injected
into this string as a text
replacement
114
RUBY_DIR="$ROOT_DIR/ruby"
source scripts/basics.sh
# http_requests will print headers and response body along with stack dumps
# if the env variable DEBUG_HTTP_REQUESTS exists
ruby_web_client () {
local program=$1
ruby -e "
require 'json'
require '$CLIENTS_DIR/web'
$program
"
}
http_request () {
local version=$1
local method=$2
local address=$3
local endpoint=$4
local request_body=$5
ruby_web_client "
if ENV['DEBUG_HTTP_REQUESTS']
response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
puts 'REQUEST:'
puts $request_body
$request_body
end
puts 'RESPONSE:'
response.each_header do |k, v|
puts "#{k}: #{v}"
end
puts "body: #{response.body}"
puts
else
WebClient.$method($version, '$address', endpoint = $endpoint) do |req|
$request_body
end rescue nil
end
"
}
here we use it to make an
HTTP call using our Ruby
WebClient object
115
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
launch our service network
116
source scripts/ruby_web_api.sh
if [ $# -ne 1 ]; then
echo
echo "This script launches an identity infrastructure baselined at the specified port address."
echo
echo "Usage:"
echo " ./startup.sh base-port"
exit 1
fi
BASE_SERVICE_PORT=$1
source ./infrastructure.sh
heading "Creating Service Infrastructure"
echo " DOMAIN_ADDRESS = $DOMAIN_ADDRESS"
echo " LOGGING_ADDRESS = $LOGGING_ADDRESS"
echo " SECURE_STORE_ADDRESS = $SECURE_STORE_ADDRESS"
echo " REGISTRY_ADDRESS = $REGISTRY_ADDRESS"
echo " ORACLE_ADDRESS = $ORACLE_ADDRESS"
echo " BEAR_ADDRESS = $BEAR_ADDRESS"
echo " VAL_ADDRESS = $VAL_ADDRESS"
create_registry
launch_domain $DOMAIN_ADDRESS
sleep 1
launch_service logging $LOGGING_ADDRESS
launch_service secure_store $SECURE_STORE_ADDRESS
launch_service registry $REGISTRY_ADDRESS
launch_service oracle $ORACLE_ADDRESS
117
ROOT_DIR=`pwd`
REGISTRY_DIR="$ROOT_DIR/registry"
COMMANDS_DIR="$ROOT_DIR/commands"
MODELS_DIR="$ROOT_DIR/models"
create_registry () {
subheading "create registry"
rm -Rf "$REGISTRY_DIR"
mkdir -p "$REGISTRY_DIR"
pushd "$REGISTRY_DIR"
ruby -e "
require '$MODELS_DIR/oracle'
require '$COMMANDS_DIR/encryption'
Console.section 'Create $REGISTRY_DIR/Oracle.db' do
oracle = Models::Oracle.new
Console.section 'Create User Zero' do
key = Encryption::create_rsa_key filename: 'keyzero.pem', save_to_disk: true
digest = OpenSSL::Digest::SHA256.new(Base64.encode64 key.to_pem)
oracle.keys.insert ID: 0,
Label: '::1',
Key: key.public_key.to_pem,
Checksum: ENV['USE_AMALGALITE'] ? digest : digest.to_s
Console.display_records oracle, :Keys
end
end
"
popd
}
create_user_database () {
local database_dir="$REGISTRY_DIR/$1"
local selfie="$ROOT_DIR/$2"
heading "create user database: $database_dir"
mkdir -p "$database_dir"
pushd "$database_dir"
ln -s "$REGISTRY_DIR/oracle.db" "$database_dir"
ln -s "$selfie" "$database_dir"
popd "$database_dir"
}
we can directly use Ruby's
OpenSSL wrapper as well
as our own API over that
118
ROOT_DIR=`pwd`
REGISTRY_DIR="$ROOT_DIR/registry"
COMMANDS_DIR="$ROOT_DIR/commands"
MODELS_DIR="$ROOT_DIR/models"
create_registry () {
subheading "create registry"
rm -Rf "$REGISTRY_DIR"
mkdir -p "$REGISTRY_DIR"
pushd "$REGISTRY_DIR"
ruby -e "
require '$MODELS_DIR/oracle'
require '$COMMANDS_DIR/encryption'
Console.section 'Create $REGISTRY_DIR/Oracle.db' do
oracle = Models::Oracle.new
Console.section 'Create User Zero' do
key = Encryption::create_rsa_key filename: 'keyzero.pem', save_to_disk: true
digest = OpenSSL::Digest::SHA256.new(Base64.encode64 key.to_pem)
oracle.keys.insert ID: 0,
Label: '::1',
Key: key.public_key.to_pem,
Checksum: ENV['USE_AMALGALITE'] ? digest : digest.to_s
Console.display_records oracle, :Keys
end
end
"
popd
}
create_user_database () {
local database_dir="$REGISTRY_DIR/$1"
local selfie="$ROOT_DIR/$2"
heading "create user database: $database_dir"
mkdir -p "$database_dir"
pushd "$database_dir"
ln -s "$REGISTRY_DIR/oracle.db" "$database_dir"
ln -s "$selfie" "$database_dir"
popd "$database_dir"
}
we're also able to use
SQLite via Amalgalite
which compiles it as an
in-process extension
119
#!/bin/bash
# (c) 2018 Innovative Identity Solutions Limited
# all rights reserved
source scripts/ruby_web_api.sh
print_cic_statement
BASE_SERVICE_PORT=9000
source ./infrastructure.sh
while getopts b:v:sh option
do
case "${option}" in
h) echo
echo "This script launches the infrastructure for user registration and interaction."
echo "For each user and the oracle it creates a running web service."
echo "It initialises the database when it runs."
echo
echo "Usage:"
echo " ./demo.sh -b bearer-name -v validator-name"
echo " ./demo.sh -h"
echo " ./demo.sh -s"
exit 0
;;
b) BEARER=${OPTARG};;
v) VALIDATOR=${OPTARG};;
s) shutdown $DOMAIN_ADDRESS;;
esac
done
if [ -z ${BEARER+x} ]; then
echo "specify bearer name with -b";
exit 1
fi
if [ -z ${VALIDATOR+x} ]; then
echo "specify validator name with -v";
exit 2
fi
scripts/startup.sh $BASE_SERVICE_PORT
heading "Launching bearer devices"
launch_bearer $BEAR_SERVICE $BEARER "bear.jpg"
launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg"
to create Ruby web services
120
source "$SCRIPTS_DIR/ruby_web_client.sh"
launch_ruby_service () {
local service=$1
local address=$2
local directory="$REGISTRY_DIR$3"
local command_key=$4
pushd "$directory"
ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" &
wait_for_process_launch
popd
}
launch_service () {
local service=$1
local address=$2
local command_key=$3
local service_name="$service""_service"
http_request :v1 post $DOMAIN_ADDRESS :A "
req.set_form_data name: '$service_name', address: '$address'"
launch_ruby_service "$service" "$address" "" "$command_key"
}
halt_service () {
local version=$1
local address=$2
local command_key=$3
http_request :v1 shutdown $address nil "req.body = '$command_key'"
}
launch_bearer () {
local port="$1"
local name="$2"
local selfie="$3"
local command_key="$4"
create_user_database "$name" "$selfie"
pushd "$REGISTRY_DIR/$name"
PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" &
sleep 1
popd
}
we need this to make web requests
121
source "$SCRIPTS_DIR/ruby_web_client.sh"
launch_ruby_service () {
local service=$1
local address=$2
local directory="$REGISTRY_DIR$3"
local command_key=$4
pushd "$directory"
ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" &
wait_for_process_launch
popd
}
launch_service () {
local service=$1
local address=$2
local command_key=$3
local service_name="$service""_service"
http_request :v1 post $DOMAIN_ADDRESS :A "
req.set_form_data name: '$service_name', address: '$address'"
launch_ruby_service "$service" "$address" "" "$command_key"
}
halt_service () {
local version=$1
local address=$2
local command_key=$3
http_request :v1 shutdown $address nil "req.body = '$command_key'"
}
launch_bearer () {
local port="$1"
local name="$2"
local selfie="$3"
local command_key="$4"
create_user_database "$name" "$selfie"
pushd "$REGISTRY_DIR/$name"
PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" &
sleep 1
popd
}
we can also start Ruby programs
with dynamically set Environment
Variables to configure them
122
source "$SCRIPTS_DIR/ruby_web_client.sh"
launch_ruby_service () {
local service=$1
local address=$2
local directory="$REGISTRY_DIR$3"
local command_key=$4
pushd "$directory"
ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" &
wait_for_process_launch
popd
}
launch_service () {
local service=$1
local address=$2
local command_key=$3
local service_name="$service""_service"
http_request :v1 post $DOMAIN_ADDRESS :A "
req.set_form_data name: '$service_name', address: '$address'"
launch_ruby_service "$service" "$address" "" "$command_key"
}
halt_service () {
local version=$1
local address=$2
local command_key=$3
http_request :v1 shutdown $address nil "req.body = '$command_key'"
}
launch_bearer () {
local port="$1"
local name="$2"
local selfie="$3"
local command_key="$4"
create_user_database "$name" "$selfie"
pushd "$REGISTRY_DIR/$name"
PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" &
sleep 1
popd
}
for each credential bearer in our
system we can launch a custom
ruby process in the background
to handle their behaviour
123
known by their works
Love is a poet, love sings the songs
Pointing his
fi
nger you follow along
Voices are calling,
The monster wants out of you
Paws you and claws you, you try not to fall
- The Beast, Concrete Blonde
124
● I have mixed feelings
on patents
● I filed some, and selling
the IP paid for several
years of research
● it also means people
can see what I do
● but the process can be
complicated
● and many patents suck
The Agony & The Ecstasy
125
● original inventions
● not preexisting in
nature - except biotech
● no maths - unless it's
software and you're in
the US
● must have a concrete
implementation
● cannot have been
published before
What Can We Patent?
Dell? Mac? WTF?!?!
126
● inventors have to publish
how their invention works
- except Marconi?
● the patent provides a
fixed term monopoly
● but the description of the
invention is in the public
domain
● only granted claims are
enforceable
Why Should We Patent?
Nikola Tesla!
127
github://feyeleanor
slideshare://feyeleanor
leanpub://GoNotebook
https://shayk.online:3000
http://inidsol.uk

Contenu connexe

Similaire à [2023] Putting the R! in R&D.pdf

PERTEMUAN 9B APLIKASI INTEGRAL.ppt
PERTEMUAN 9B APLIKASI  INTEGRAL.pptPERTEMUAN 9B APLIKASI  INTEGRAL.ppt
PERTEMUAN 9B APLIKASI INTEGRAL.pptTiodoraSihombing
 
Numerical Methods: curve fitting and interpolation
Numerical Methods: curve fitting and interpolationNumerical Methods: curve fitting and interpolation
Numerical Methods: curve fitting and interpolationNikolai Priezjev
 
8 queens problem using back tracking
8 queens problem using back tracking8 queens problem using back tracking
8 queens problem using back trackingTech_MX
 
M.sheela complex ppt
M.sheela complex pptM.sheela complex ppt
M.sheela complex pptMSheelaSheela
 
Classical String Calculations in curved space
Classical String Calculations in curved spaceClassical String Calculations in curved space
Classical String Calculations in curved spaceIsmail Abdulaziz
 
presentation.pptx
presentation.pptxpresentation.pptx
presentation.pptxahmed219190
 
Derivada aplicada en la carrera de electrónica y automatización.
Derivada aplicada en la carrera de electrónica y automatización.Derivada aplicada en la carrera de electrónica y automatización.
Derivada aplicada en la carrera de electrónica y automatización.DANIELAXIOMARAANDRAN
 
[Maths] arithmetic
[Maths] arithmetic[Maths] arithmetic
[Maths] arithmeticOurutopy
 
HW 5-RSAascii2str.mfunction str = ascii2str(ascii) .docx
HW 5-RSAascii2str.mfunction str = ascii2str(ascii)        .docxHW 5-RSAascii2str.mfunction str = ascii2str(ascii)        .docx
HW 5-RSAascii2str.mfunction str = ascii2str(ascii) .docxwellesleyterresa
 
Algebra Trigonometry Problems
Algebra Trigonometry ProblemsAlgebra Trigonometry Problems
Algebra Trigonometry ProblemsDon Dooley
 
Cbse Class 12 Maths Sample Paper 2013 Model 3
Cbse Class 12 Maths Sample Paper 2013 Model 3Cbse Class 12 Maths Sample Paper 2013 Model 3
Cbse Class 12 Maths Sample Paper 2013 Model 3Sunaina Rawat
 
Differential geometry three dimensional space
Differential geometry   three dimensional spaceDifferential geometry   three dimensional space
Differential geometry three dimensional spaceSolo Hermelin
 
Data sparse approximation of the Karhunen-Loeve expansion
Data sparse approximation of the Karhunen-Loeve expansionData sparse approximation of the Karhunen-Loeve expansion
Data sparse approximation of the Karhunen-Loeve expansionAlexander Litvinenko
 
Data sparse approximation of Karhunen-Loeve Expansion
Data sparse approximation of Karhunen-Loeve ExpansionData sparse approximation of Karhunen-Loeve Expansion
Data sparse approximation of Karhunen-Loeve ExpansionAlexander Litvinenko
 
10.2 using combinations and the binomial theorem
10.2 using combinations and the binomial theorem10.2 using combinations and the binomial theorem
10.2 using combinations and the binomial theoremhartcher
 

Similaire à [2023] Putting the R! in R&D.pdf (20)

PERTEMUAN 9B APLIKASI INTEGRAL.ppt
PERTEMUAN 9B APLIKASI  INTEGRAL.pptPERTEMUAN 9B APLIKASI  INTEGRAL.ppt
PERTEMUAN 9B APLIKASI INTEGRAL.ppt
 
Numerical Methods: curve fitting and interpolation
Numerical Methods: curve fitting and interpolationNumerical Methods: curve fitting and interpolation
Numerical Methods: curve fitting and interpolation
 
8 queens problem using back tracking
8 queens problem using back tracking8 queens problem using back tracking
8 queens problem using back tracking
 
4900514.ppt
4900514.ppt4900514.ppt
4900514.ppt
 
Tcs 2014 saved in 97-2003 format
Tcs 2014 saved in 97-2003 formatTcs 2014 saved in 97-2003 format
Tcs 2014 saved in 97-2003 format
 
M.sheela complex ppt
M.sheela complex pptM.sheela complex ppt
M.sheela complex ppt
 
Classical String Calculations in curved space
Classical String Calculations in curved spaceClassical String Calculations in curved space
Classical String Calculations in curved space
 
presentation.pptx
presentation.pptxpresentation.pptx
presentation.pptx
 
Derivada aplicada en la carrera de electrónica y automatización.
Derivada aplicada en la carrera de electrónica y automatización.Derivada aplicada en la carrera de electrónica y automatización.
Derivada aplicada en la carrera de electrónica y automatización.
 
1st Semester Physics Cycle (Dec-2015; Jan-2016) Question Papers
1st Semester Physics Cycle  (Dec-2015; Jan-2016) Question Papers1st Semester Physics Cycle  (Dec-2015; Jan-2016) Question Papers
1st Semester Physics Cycle (Dec-2015; Jan-2016) Question Papers
 
[Maths] arithmetic
[Maths] arithmetic[Maths] arithmetic
[Maths] arithmetic
 
Binomial theorem
Binomial theorem Binomial theorem
Binomial theorem
 
HW 5-RSAascii2str.mfunction str = ascii2str(ascii) .docx
HW 5-RSAascii2str.mfunction str = ascii2str(ascii)        .docxHW 5-RSAascii2str.mfunction str = ascii2str(ascii)        .docx
HW 5-RSAascii2str.mfunction str = ascii2str(ascii) .docx
 
Algebra Trigonometry Problems
Algebra Trigonometry ProblemsAlgebra Trigonometry Problems
Algebra Trigonometry Problems
 
Cbse Class 12 Maths Sample Paper 2013 Model 3
Cbse Class 12 Maths Sample Paper 2013 Model 3Cbse Class 12 Maths Sample Paper 2013 Model 3
Cbse Class 12 Maths Sample Paper 2013 Model 3
 
Differential geometry three dimensional space
Differential geometry   three dimensional spaceDifferential geometry   three dimensional space
Differential geometry three dimensional space
 
Data sparse approximation of the Karhunen-Loeve expansion
Data sparse approximation of the Karhunen-Loeve expansionData sparse approximation of the Karhunen-Loeve expansion
Data sparse approximation of the Karhunen-Loeve expansion
 
Slides
SlidesSlides
Slides
 
Data sparse approximation of Karhunen-Loeve Expansion
Data sparse approximation of Karhunen-Loeve ExpansionData sparse approximation of Karhunen-Loeve Expansion
Data sparse approximation of Karhunen-Loeve Expansion
 
10.2 using combinations and the binomial theorem
10.2 using combinations and the binomial theorem10.2 using combinations and the binomial theorem
10.2 using combinations and the binomial theorem
 

Plus de Eleanor McHugh

Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsEleanor McHugh
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityEleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveEleanor McHugh
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionEleanor McHugh
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]Eleanor McHugh
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with goEleanor McHugh
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxEleanor McHugh
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored SpacesEleanor McHugh
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignEleanor McHugh
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by designEleanor McHugh
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trustEleanor McHugh
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoEleanor McHugh
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleEleanor McHugh
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionEleanor McHugh
 
Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoEleanor McHugh
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goEleanor McHugh
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountabilityEleanor McHugh
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CEleanor McHugh
 

Plus de Eleanor McHugh (20)

Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By Design
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
 
Hello Go
Hello GoHello Go
Hello Go
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
 
Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with Go
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
 

Dernier

My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 

Dernier (20)

My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 

[2023] Putting the R! in R&D.pdf

  • 1. 1 Eleanor McHugh co-founder @ InIdSol https://inidsol.uk https://shayk.online x://@feyeleanor leanpub://GoNotebook slideshare://feyeleanor linkedin://in/eleanormchugh putting the R! in R&D Rough Cut
  • 2. 2 solving puzzles the hard way Elric sent his mind into twisting tunnels of logic, across endless plains of ideas, through mountains of symbolism and endless universes of alternate truths; he sent his mind out further and further and as it went he sent with it the words [...] words that few of his contemporaries would understand... - Elric of Melniboné, Michael Moorcock
  • 3. 3 solving puzzles the hard way: the ratio of squares inscribe a circle inside a square ao the circle touches the sides at their midpoint inscribe a square ai inside the circle its vertices touch the circumference ai ao
  • 4. 4 2r 2πr 2r ai ao solving puzzles the hard way: the ratio of squares we know a lot about circles their diameter is twice their radius r and their circumference is 2πr
  • 5. 5 y πd d x ai = (2y)2 ao = d2 ai ao solving puzzles the hard way: the ratio of squares and we know a lot about squares such as their area being the square of the length of one side this allows us to express the areas of the two squares in terms of d and y
  • 6. 6 y πd d x ai = 4y2 ao = d2 ai ao solving puzzles the hard way: the ratio of squares
  • 7. 7 y πd d x ai = 4y2 ao = (2x + 2y)2 ai ao solving puzzles the hard way: the ratio of squares
  • 8. 8 y πd d x ai = 4y2 ao = 4x2 + 8xy + 4y2 ai ao solving puzzles the hard way: the ratio of squares
  • 9. 9 y πd d x ai = 4y2 ao = 4x2 + 8xy + 4y2 ai ao solving puzzles the hard way: the ratio of squares note that the calculation of ao includes ai which is interesting but not directly helpful in calculating the ratio of ao to ai however this still leaves us to figure out both x and y which isn't particularly useful
  • 10. 10 y πd d x ai ao solving puzzles the hard way: the ratio of squares however we can reframe this problem if we bisect ai along the line formed by opposing vertices we find that this has shares the length d - the circle diameter d
  • 11. 11 y πd d x h2 = o2 + a2 d2 = (2y)2 + (2y)2 ai ao solving puzzles the hard way: the ratio of squares and by applying the pythagorean theorem we can calculate d in terms of y d
  • 12. 12 y πd d x h2 = o2 + a2 d2 = 4y2 + 4y2 ai ao solving puzzles the hard way: the ratio of squares d
  • 13. 13 y πd d x h2 = o2 + a2 d2 = 8y2 ai ao solving puzzles the hard way: the ratio of squares d
  • 14. 14 y πd d x ao = 8y2 ai = (2y)2 ai ao solving puzzles the hard way: the ratio of squares d
  • 15. 15 y πd d x ao = 8y2 ai = 4y2 ai ao solving puzzles the hard way: the ratio of squares d
  • 16. 16 y πd d x ao : ai = 8 : 4 ao : ai = 2 : 1 ai ao solving puzzles the hard way: the ratio of squares so ao is twice the area of ai d
  • 17. 17 *blink* A clever person solves a problem. A wise person avoids it. - Albert Einstein
  • 18. 18 *blink*: the ratio of squares algebra is a rational tool that can solve many problems by brute force however when you study a problem domain in depth you start to develop intuitions - ways of identifying shortcuts to the answer you're after ai ao d
  • 19. 19 *blink*: the ratio of squares algebra is a rational tool that can solve many problems by brute force however when you study a problem domain in depth you start to develop intuitions - ways of identifying shortcuts to the answer you're after ai ao d
  • 20. 20 *blink*: the ratio of squares if in this case we rotate ai by 45° ao ai d
  • 21. 21 *blink*: the ratio of squares we can see that the area of ao must be twice the area of ai ao ai
  • 22. 22 *blink*: the ratio of squares a y y d 2 2 Y 6 842 I s d from d 2 24 g a e 12 4 2 84 442 v using 8112 4 2 84 442 Sino I 242 42 2 4 42 x 2 4 42 0 Cos ay Sino sin450 sin450 tano Ia seco ha I E ai y coseco to ay de di 442 14472 242 12 8,2 do de 90 8 2 Sin II do Cos 450 I g 2 tan450 1 sin900 1 Cos 900 0 tango undefined
  • 24. 24 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 applied physics, microelectronics, & computing 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
  • 25. 25 ● for a particle with few degrees of freedom, its position x and its momentum p cannot both be determined at the same time ● Schrödinger's cat sums up the weirdness of this Uncertain Quanta Heisenberg Schrödinger
  • 26. 26 ● at the smallest scale things behave as if distance doesn't exist ● at the largest scale nothing can move faster then the speed of light ● which is more true? ● wormholes! ● time travel! ● (and conspiracies!!!) Locality & The Real Bell Einstein, Rosen, Podolsky
  • 27. 27 Incomplete Mathematics see https://www.quantamagazine.org/how-godels-proof-works-20200714/ ● Gödel vs formal methods ● any formal system able to do elementary arithmetic is either inconsistent or incomplete ● any formal system able to express its own consistency can prove its own consistency if and only if it is inconsistent Whitehead & Russell Gödel
  • 28. 28 Incomplete Mathematics see https://www.quantamagazine.org/how-godels-proof-works-20200714/ ● Gödel vs formal methods ● any formal system able to do elementary arithmetic is either inconsistent or incomplete ● any formal system able to express its own consistency can prove its own consistency if and only if it is inconsistent
  • 29. 29 ● Turing-Church ● robot reads infinite tape ● applies rules that can overwrite the tape then moves the tape one step left or right ● can compute anything which can be computed ● physical analogue of the Lambda Calculus Universal Machines The input value to be bound to the argument x Substitute the value into the body The body becomes the return value λ x . x ( ) 2 λ 2 . x ( ) λ 2 . 2 ( ) 2 Turing Church
  • 30. 30 ● the study of causal processes and feedback loops ● these loops regulate or control the operation of a system ● feedback can be positive or negative ● used to steer a system towards desired goals Cybernetic Noise
  • 31. 31 ● entropy describes the information contained in a system ● the higher the entropy, the more information that can be contained ● applications in cryptography and telecommunications Information Overload
  • 32. 32 Loose Lips Save Ships ● Bletchley Park GC&CS ● traffic analysis ● Enigma and the Turing electro-mechanical bombe ● Lorenz stream cipher and Colossus, the world's first electronic programmable computer Flowers
  • 33. 33 ● the Memex, an electro- mechanical platform for managing deeply interlinked knowledge ● Project Xanadu a platform for publishing hypertext & hypermedia ● WWW adds typesetting and programmability to hypertext Webs of Meaning Ted Nelson Berners-Lee
  • 34. 34 ● algorithms are tractable to rigorous analysis ● Big O notation - how long an algorithm runs ● or how much memory an algorithm uses ● O(logx n) ● O(nx) ● O(n!) Beyond the Machine in programming, simplicity and clarity ... are not a dispensable luxury, but a crucial matter that decides between success and failure Dijkstra Knuth
  • 35. 35 ● falsifiability as the test of empirical study ● constructivism - the pursuit of knowledge is shaped by social factors ● the methods of one paradigm do not necessarily translate into another paradigm All Life is Problem Solving In so far as a scientific statement speaks about reality, it must be falsifiable; and in so far as it is not falsifiable it does not speak about reality Kuhn Popper
  • 36. 36 that first deep-dive into insanity Love is the ghost haunting your head Love is the killer you thought was your friend Love is the creature who lives in the dark Sneaks up, will stick you And painfully pick you apart - The Beast, Concrete Blonde
  • 37. 37
  • 38. 38
  • 39. 39
  • 40. 40
  • 41. 41 ● stack-based ● programs compose word definitions from a threaded dictionary ● limited type system ● ASM versions are great for embedded systems ● Open Firmware ● gforth ● Factor (functional) Forth
  • 42. 5 2 3 56 76 23 65 .s <7> 5 2 3 56 76 23 65 ok 5 4 + . 9 ok 13 2 / . 6 ok 13 2 mod . 1 ok 3 dup - . 0 ok 2 5 swap / . 2 ok 6 4 5 rot .s <3> 4 5 6 ok 4 0 drop 2 / . 2 ok 1 2 3 nip .s <2> 1 3 ok : square ( n -- n ) dup * ; ok 5 square . 25 ok see square : square dup * ; ok 42 42 = . -1 ok 12 53 = . 0 ok : ?>64 dup 64 > if ." More than" else ." Less than" then ." 64!" ; ok 100 ?>64 More than 64! ok 20 ?>64 Less than 64! ok : squares ( n -- ) 1 do i square loop ; ok 5 squares .s <4> 1 4 9 16 ok : threes ( n n -- ) ?do i . 3 +loop ; ok 15 0 threes 0 3 6 9 12 ok 0 0 threes ok variable age ok 21 age ! ok age @ . 21 ok age ? 21 ok 100 constant WATER-BOILING-POINT ok WATER-BOILING-POINT . 100 ok variable num-array 2 cells allot ok num-array 3 cells erase ok num-array 3 cells 0 fill ok create num-array 64 , 9001 , 1337 , ok 0 cells num-array + ? 64 ok 1 cells num-array + ? 9001 ok : of-arr ( n n -- n ) cells + ; ok num-array 2 of-arr ? 1337 ok 20 num-array 1 of-arr ! ok num-array 1 of-arr ? 20 ok : i-from-rstack ( -- ) 4 0 do r@ . loop ; ok i-from-rstack 0 1 2 3 ok 5 6 4 >r swap r> .s 6 5 4 ok 5 6 4 clearstack ok bye 42 see https://learnxinyminutes.com/docs/forth/
  • 43. 5 2 3 56 76 23 65 .s <7> 5 2 3 56 76 23 65 ok 5 4 + . 9 ok 13 2 / . 6 ok 13 2 mod . 1 ok 3 dup .s cr - . <2> 3 3 0 ok 43
  • 44. 2 5 swap .s <2> 5 2 ok 6 4 5 rot . <3> 4 5 6 ok 4 0 drop 2 / . 2 ok 1 2 3 nip .s <2> 1 3 ok 4 5 6 clearstack .s <0> ok 44
  • 45. : square ( n -- n ) dup * ; ok 5 square . 25 ok see square : square dup * ; ok 45
  • 46. : print-result . cr .s ; 12 42 42 42 = print-result cr = print-result -1 <2> 12 42 0 <0> ok : ?>64 dup 64 > if ." More than" else ." Less than" then ." 64!" ; 100 ?>64 More than 64! ok 20 ?>64 Less than 64! ok 46
  • 47. : squares ( n -- ) 1 do i square loop ; 5 .s .cr squares .s <1> 5 <4> 1 4 9 16 ok : threes ( n n -- ) ?do i 3 +loop ; : reverse-stack ( n*x -- n*x') depth 1 do i roll loop ; : print-stack ( n -- ) depth 0 do . cr loop ; 15 0 threes cr .s cr reverse-stack .s cr print-stack <5> 0 3 6 9 12 ok <5> 12 9 6 3 0 ok 0 3 6 9 12 ok 0 0 threes ok 47
  • 48. variable age ok 21 age ! ok age @ . 21 ok age ? 21 ok 48
  • 49. variable multiplier : multiples ( n n -- ) ?do i multiplier @ +loop ; 3 multiplier ! 20 0 multiples cr .s cr reverse-stack .s <7> 0 3 6 9 12 15 18 <7> 18 15 12 9 6 3 0 ok 2 multiplier ! 20 0 multiples cr .s cr reverse-stack .s <10> 2 4 6 8 10 12 14 16 18 <10> 16 14 12 10 8 6 4 2 0 ok 4 multiplier ! 20 0 multiples cr .s cr reverse-stack .s <5> 0 4 8 12 16 <5> 16 12 8 4 0 ok 49
  • 50. : multiples ( n n -- ) ?do i MULTIPLIER +loop ; :1: Undefined word : multiples ( n n -- ) ?do i >>>MULTIPLIER<<< +loop ; Backtrace: $105349A20 throw $10535FC48 no.extensions $10534D358 compiler-notfound1 3 constant MULTIPLIER 20 0 multiples cr .s cr reverse-stack .s <7> 0 3 6 9 12 15 18 <7> 18 15 12 9 6 3 0 ok 4 constant MULTIPLIER redefined MULTIPLIER ok 20 0 multiples cr .s cr reverse-stack .s <7> 0 3 6 9 12 15 18 <7> 18 15 12 9 6 3 0 ok 50
  • 51. variable num-array 2 cells allot ok num-array 3 cells erase num-array 3 cells 0 fill ok create num-array 64 , 9001 , 1337 , ok 0 cells num-array + ? 64 ok 1 cells num-array + ? 9001 ok 51
  • 52. : of-arr ( n n -- n ) cells + ; create num-array 64 , 9001 , 1337 , num-array 2 of-arr ? 1337 ok 20 num-array 2 of-arr ! ok num-array 2 of-arr ? 20 ok 52
  • 53. : i-from-rstack ( -- ) 4 0 do r@ . loop ; i-from-rstack 0 1 2 3 ok 5 6 4 cr .s cr >r .s cr r@ . cr swap .s cr r> .s <3> 5 6 4 <2> 5 6 4 <2> 6 5 <3> 6 5 4 ok 53
  • 54. 54 ● tokenised interpreter ● running on Zilog Z80 ● unstructured code with GOTO and GOSUB ● no UDTs ● simple line editor ● painfully slow execution ● if you can code in this you can probably code in anything Locomotive BASIC
  • 55. 1 REM ****************** 2 REM * Amstrad Forth * 3 REM * by * 4 REM * Stephen Devine * 5 REM ****************** 6 REM 10 REM (c) Computing with the Amstrad 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 250 REM Input Commands 260 w$="":er=0:LINE INPUT ln$:IF ln$="" THEN 690 ELSE IF LEN(ln$)>240 THEN PRINT"Line too long":GOTO 260 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":G$ 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 55 https://www.cpcwiki.eu/index.php/CWTA_Issue_17_-_May_1986_-_Type-Ins Used under Fair Use for purpose of review and critique
  • 56. 56 1 REM ****************** 2 REM * Amstrad Forth * 3 REM * by * 4 REM * Stephen Devine * 5 REM ****************** 6 REM 10 REM (c) Computing with the Amstrad 100 REM Initialisation 250 REM Input Commands 680 REM Error Routine 710 REM Compile New Word 750 REM Execute Commands 1080 REM Command List 1690 REM Process Editing Commands 2540 REM Data for Core Words Outer Interpreter (tokeniser & parser) Word Compiler (adds entry to dictionary) Inner Interpreter (invoke entries from dictionary) Implemented Primitives Implementation extension words Primitive tokens and stack behaviour
  • 57. 57 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 58. 58 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 59. 59 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 60. 60 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 61. 61 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 62. 62 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 63. 63 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 64. 64 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 65. 65 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 66. 66 100 REM Initialisation 110 MODE 2:BORDER 13:INK 1,0:INK 0,13 120 forth$=CHR$(12)+"Fred Forth V1.1" 130 OPENOUT "dummy":MEMORY HIMEM-1:CLOSEOUT 140 temp=0:DEFINT a-z 150 DIM w$(130),p(130),beg(40),ff(40),df(40),loop(40),ll(40),li(40) 160 er$(0)="OK":er$(1)="Stack Underflow":er$(2)="Empty Stack" 170 er$(3)=" already defined":er$(4)=" - Illegal variable name":er$(5)=" - Bad Word":er$(6)="Stack Full":er$(7)="Return Stack Full" 180 spmax=100:DIM s(spmax):sp=-1 190 cvn=58:DIM cvoc$(cvn),dsp(cvn,1) 200 FOR i=0 TO cvn:READ cvoc$(i),dsp(i,0),dsp(i,1):NEXT 210 cvoc$(5)="."+CHR$(34) 220 umax=100:vmax=100:DIM uvoc$(umax),uvex$(umax),var$(vmax),var(vmax) 230 uvn=-1:vrn=-1:PRINT forth$:PRINT:PRINT er$(0) 240 ON ERROR GOTO 2530 2530 er=6:IF sp>100 THEN sp=100:RESUME NEXT ELSE w$="":RESUME 690 2540 REM Data for Core Words 2550 DATA "!",2,-2,"*",2,-1,"+",2,-1,"-",2,-1,".",0,-1,"?",0,0,"/",2,-1,"/ MOD",2,0,"0<",1,0,"0=",1,0,"<",2,-1 2560 DATA "=",2,-1,">",2,-1,"?",1,-1,"@",1,0,"ABS",1,0,"AND",2,-1,"C@",1,0,"CR",0,0,"DROP",1,-1,"DUP",1,1 2570 DATA "EMIT",1,-1,"KEY",0,1,"MAX",2,-1,"MIN",2,-1,"MINUS",1,0,"MOD",2,-1,"OR",2,-1,"OVER",2,1 2580 DATA "SPACE",0,0,"SPACES",1,-1,"SWAP",2,0,"VARIABLE",1,-1,"XOR",2,-1,"BEGIN",0,0,"UNTIL",1,-1 2590 DATA "WHILE",1,-1,"REPEAT",0,0,"IF",1,-1,"THEN",0,0,"ELSE",0,0,"FORTH",0,0,"CLEAR",0,0,"ROT",3,0,"DO",2, -2,"LOOP",0,0,"I",0,+1 2600 REM Data for Amstrad Words 2610 DATA "CLG",1,-1,"DRAW",2,-2,"DRAWR",2,-2,"FRE",0,1,"MOVE",2,-2,"MOVER",2,-2 2620 DATA "PLOT",2,-2,"PLOTR",2,-2,"RND",0,1,"TEST",2,-1,"TESTR",2,-1,"GRAPEN",1,-1
  • 68. 68 250 REM Input Commands 260 w$="":er=0:LINE INPUT ln$:IF ln$="" THEN 690 ELSE IF LEN(ln$)>240 THEN PRINT"Line too long":GOTO 260 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 680 REM Error Routine 690 IF POS(#0)>1 THEN PRINT CHR$(32); 700 PRINT w$;er$(er):GOTO 260
  • 69. 69 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 produce token stream
  • 70. 70 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 look for extension words
  • 71. 71 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 outer interpreter loop
  • 72. 72 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 word definition to compile
  • 73. 73 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 execute "byte code" or add to dictionary check for user defined word check for user defined variable must be a number "byte code" generated for token
  • 74. 74 270 WHILE ASC(ln$)=32:IF LEN(ln$)>1 THEN ln$=RIGHT$(ln$,LEN(ln$)-1):WEND ELSE 690 280 WHILE RIGHT$(ln$,1)=CHR$(32):ln$=LEFT$(ln$,LEN(ln$)-1):WEND 290 ln$=UPPER$(ln$):IF ASC(ln$)=ASC("*") THEN IF LEN(ln$)>1 AND LEFT$(ln$,2)<>"* " THEN GOSUB 1700:IF er THEN 260 ELSE w$="":GOTO 690 300 ln$=ln$+CHR$(32):x$="":q=1:wn=-1:comp=0 310 WHILE q<LEN(ln$) 320 p=q:WHILE MID$(ln$,q,1)<>" ":q=q+1:WEND 330 w$=MID$(ln$,p,q-p):IF w$=":" THEN IF wn=-1 AND RIGHT$(ln$,2)="; " THEN comp=-1:GOTO 640 ELSE PRINT"Bad definition":GOTO 260 340 FOR i=cvn TO 0 STEP-1:IF cvoc$(i)<>w$ THEN NEXT:GOTO 400 350 IF comp THEN IF wn=0 THEN er=3:GOTO 690 360 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 370 x$=x$+CHR$(0)+CHR$(i+14):IF w$<>"."+CHR$(34) THEN 640 380 te=INSTR(q,ln$,CHR$(34)+CHR$(32)):IF te=0 THEN PRINT".";CHR$(34);" without ";CHR$(34):GOTO 260 390 x$=x$+MID$(ln$,q+1,te-q-1)+CHR$(4):q=te+1:GOTO 640 400 FOR i=uvn TO 0 STEP-1:IF uvoc$(i)<>w$ THEN NEXT:GOTO 440 410 IF comp THEN IF wn=0 THEN er=3:GOTO 690 420 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=4:GOTO 690 430 x$=x$+CHR$(1)+CHR$(i+14):GOTO 640 440 FOR i=vrn TO 0 STEP-1:IF var$(i)<>w$ THEN NEXT:GOTO 480 450 IF comp THEN IF wn=0 THEN er=3:GOTO 690 460 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=3:GOTO 690 470 x$=x$+CHR$(2)+CHR$(i+14):GOTO 640 480 FOR i=1 TO LEN(w$) 490 IF i=1 AND (ASC(w$)=ASC("+") OR ASC(w$)=ASC("-")) AND LEN(w$)>1 THEN 510 500 IF MID$(w$,i,1)<"0" OR MID$(w$,i,1)>"9" THEN 560 510 NEXT i 520 IF comp AND wn=0 THEN er=5:GOTO 690 530 IF wn>=0 THEN IF w$(wn)="VARIABLE" THEN er=5:GOTO 690 540 IF VAL(w$)>32767 OR VAL(w$)<-32767 THEN PRINT"Number ";w$;" too large":GOTO 260 550 x$=x$+CHR$(3)+w$+CHR$(4):GOTO 640 560 IF wn<0 THEN 590 ELSE IF w$(wn)<>"VARIABLE" THEN 590 570 IF comp AND w$=w$(1) THEN er=3:GOTO 690 580 x$=x$+w$+CHR$(4):GOTO 640 590 IF w$<>";" THEN 610 600 IF comp=0 OR q<>LEN(ln$) THEN PRINT"Illegal semi-colon":GOTO 260 ELSE 640 610 IF comp THEN IF wn=0 THEN 640 620 IF comp THEN IF w$<>w$(1) THEN er=5:GOTO 690 ELSE x$=x$+CHR$(1)+CHR$(uvn+15):GOTO 640 630 er=5:GOTO 690 640 wn=wn+1:w$(wn)=w$ 650 WHILE MID$(ln$,q,1)=" ":q=q+1:WEND 660 WEND 670 x$=x$+CHR$(13):IF comp THEN 720 ELSE 760 add "byte code" for primitive add "byte code" for user defined word add "byte code" for user defined variable add "byte code" for number compiler mode sanity checks
  • 76. 76 710 REM Compile New Word 720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260 730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$ 740 w$="":GOTO 690
  • 77. 77 710 REM Compile New Word 720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260 730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$ 740 w$="":GOTO 690
  • 78. 78 710 REM Compile New Word 720 IF wn<3 THEN PRINT"Insufficient definition":GOTO 260 730 uvn=uvn+1:uvoc$(uvn)=w$(1):uvex$(uvn)=x$ 740 w$="":GOTO 690
  • 80. 80 750 REM Execute Commands 760 ln=0:w$(ln)=x$:er=0 770 GOSUB 780:w$="":GOTO 690 780 p(ln)=1:ff(ln)=0:df(ln)=0 790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13) 800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1 810 IF class<>0 THEN 920 820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860 840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1 850 GOTO 1060 860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070 870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070 880 sp=sp+dsp(word,1) 890 IF word <43 THEN ON word+1 GOSUB 1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290 ,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149 0,1500,1510,1520 900 IF word>42 THEN ON word-42 GOSUB 1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680 910 IF er=0 THEN 1060 ELSE 1070 920 IF class<>1 THEN 970 930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 940 IF ff(ln) THEN 1060 950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN 960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN 970 IF class<>2 THEN 1010 980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 990 IF ff(ln) THEN 1060 1000 sp=sp+1:s(sp)=@var(word):GOTO 1060 1010 IF class<>3 THEN er=1:GOTO 1070 1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND 1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1 1040 IF ff(ln) THEN 1060 1050 sp=sp+1:s(sp)=v 1060 WEND 1070 ln=ln-1:RETURN
  • 81. 81 750 REM Execute Commands 760 ln=0:w$(ln)=x$:er=0 770 GOSUB 780:w$="":GOTO 690 780 p(ln)=1:ff(ln)=0:df(ln)=0 790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13) 800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1 810 IF class<>0 THEN 920 820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860 840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1 850 GOTO 1060 860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070 870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070 880 sp=sp+dsp(word,1) 890 IF word <43 THEN ON word+1 GOSUB 1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290 ,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149 0,1500,1510,1520 900 IF word>42 THEN ON word-42 GOSUB 1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680 910 IF er=0 THEN 1060 ELSE 1070 920 IF class<>1 THEN 970 930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 940 IF ff(ln) THEN 1060 950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN 960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN 970 IF class<>2 THEN 1010 980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 990 IF ff(ln) THEN 1060 1000 sp=sp+1:s(sp)=@var(word):GOTO 1060 1010 IF class<>3 THEN er=1:GOTO 1070 1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND 1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1 1040 IF ff(ln) THEN 1060 1050 sp=sp+1:s(sp)=v 1060 WEND 1070 ln=ln-1:RETURN these are our execution classes 0 = primitives 1 = user defined word 2 = user defined variable 3 = numbers
  • 82. 82 750 REM Execute Commands 760 ln=0:w$(ln)=x$:er=0 770 GOSUB 780:w$="":GOTO 690 780 p(ln)=1:ff(ln)=0:df(ln)=0 790 WHILE MID$(w$(ln),p(ln),1)<>CHR$(13) 800 class=ASC(MID$(w$(ln),p(ln),1)):p(ln)=p(ln)+1 810 IF class<>0 THEN 920 820 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 830 IF ff(ln)=0 OR word=37 OR word=39 OR word=40 THEN 860 840 IF word=5 OR word=32 THEN WHILE ASC(MID$(w$(ln),p(ln),1))<>4:p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1 850 GOTO 1060 860 IF sp+dsp(word,1)<-1 OR sp+dsp(word,1)>spmax THEN er=1:GOTO 1070 870 IF sp-dsp(word,0)<-1 THEN er=2:GOTO 1070 880 sp=sp+dsp(word,1) 890 IF word <43 THEN ON word+1 GOSUB 1090,1110,1120,1130,1140,1150,1160,1170,1180,1190,1200,1210,1220,1230,1240,1250,1260,1270,1280,1290 ,1300,1310,1320,1330,1340,1350,1360,1370,1380,1390,1400,1410,1420,1430,1440,1450,1460,1470,1480,149 0,1500,1510,1520 900 IF word>42 THEN ON word-42 GOSUB 1530,1540,1550,1560,1570,1580,1590,1600,1610,1620,1630,1640,1650,1660,1670,1680 910 IF er=0 THEN 1060 ELSE 1070 920 IF class<>1 THEN 970 930 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 940 IF ff(ln) THEN 1060 950 IF ln<34 THEN ln=ln+1:w$(ln)=uvex$(word) ELSE er=7:RETURN 960 GOSUB 780:IF ln=0 OR er=0 THEN 1060 ELSE RETURN 970 IF class<>2 THEN 1010 980 word=ASC(MID$(w$(ln),p(ln),1))-14:p(ln)=p(ln)+1 990 IF ff(ln) THEN 1060 1000 sp=sp+1:s(sp)=@var(word):GOTO 1060 1010 IF class<>3 THEN er=1:GOTO 1070 1020 p=p(ln):WHILE ASC(MID$(w$(ln),p,1))<>4:p=p+1:WEND 1030 v=VAL(MID$(w$(ln),p(ln),p-p(ln)+1)):p(ln)=p+1 1040 IF ff(ln) THEN 1060 1050 sp=sp+1:s(sp)=v 1060 WEND 1070 ln=ln-1:RETURN these are computed GOSUBs implementing a despatch table to BASIC for each primitive
  • 83. 83 1080 REM Command List 1090 temp!=s(sp+1):IF temp!<0 THEN temp!=temp!+65536 1100 POKE s(sp+2),temp!-256*INT(temp!/256):POKE s(sp+2)+1,INT(temp!/256):RETURN 1110 s(sp)=s(sp)*s(sp+1):RETURN 1120 s(sp)=s(sp)+s(sp+1):RETURN 1130 s(sp)=s(sp)-s(sp+1):RETURN 1140 PRINT s(sp+1);CHR$(8);:RETURN 1150 WHILE ASC(MID$(w$(ln),p(ln),1))<>4:PRINT MID$(w$(ln),p(ln),1);:p(ln)=p(ln)+1:WEND:p(ln)=p(ln) +1:RETURN 1160 s(sp)=INT(s(sp)/s(sp+1)):RETURN 1170 temp=s(sp):s(sp)=INT(s(sp-1)/s(sp)):s(sp-1)=s(sp-1)-s(sp)*temp:RETURN 1180 s(sp)=(s(sp)<0):RETURN 1190 s(sp)=(s(sp)=0):RETURN 1200 s(sp)=(s(sp)<s(sp+1)):RETURN 1210 s(sp)=(s(sp)=s(sp+1)):RETURN 1220 s(sp)=(s(sp)>s(sp+1)):RETURN 1230 temp!=PEEK(s(sp+1))+256*PEEK(s(sp+1)+1):IF temp!>32767 THEN temp! =temp!-65536:PRINTtemp!;CHR$(8);:RETURN ELSE PRINTtemp!;CHR$(8);:RETURN 1240 temp!=PEEK(s(sp))+256*PEEK(s(sp)+1):IF temp!>32767 THEN s(sp)=temp!-65536:RETURN ELSE s(sp)=temp!:RETURN 1250 s(sp)=ABS(s(sp)):RETURN 1260 s(sp)=s(sp) AND s(sp+1):RETURN 1270 s(sp)=PEEK(s(sp)):RETURN 1280 PRINT:RETURN 1290 RETURN 1300 s(sp)=s(sp-1):RETURN 1310 PRINTCHR$(s(sp+1));:RETURN 1320 in$=INKEY$:IF in$="" THEN 1320 ELSE s(sp)=ASC(in$):RETURN 1330 s(sp)=MAX(s(sp),s(sp+1)):RETURN 1340 s(sp)=MIN(s(sp),s(sp+1)):RETURN 1350 s(sp)=-s(sp):RETURN 1360 s(sp)=s(sp) MOD s(sp+1):RETURN 1370 s(sp)=s(sp) OR s(sp+1):RETURN 1380 s(sp)=s(sp-2):RETURN 1390 PRINT" ";:RETURN 1400 PRINT USING "&";SPACE$(s(sp+1)-256*INT(s(sp+1)/256));:RETURN 1410 temp=s(sp):s(sp)=s(sp-1):s(sp-1)=temp:RETURN 1420 vrn=vrn+1:var(vrn)=s(sp+1):WHILE ASC(MID$(w$(ln),p(ln),1))<>4:var$(vrn)=var$(vrn)+MID$(w$ (ln),p(ln),1):p(ln)=p(ln)+1:WEND:p(ln)=p(ln)+1:RETURN 1430 s(sp)=s(sp) XOR s(sp+1):RETURN 1440 beg(ln)=p(ln):RETURN 1450 IF s(sp+1)=0 THEN p(ln)=beg(ln):RETURN ELSE RETURN 1460 IF s(sp+1)<>0 THEN RETURN ELSE ff(ln)=-1:RETURN this is why switch statements exist and why fallthrough is superior to break!
  • 84. 84 that's probably more than you ever wanted to know about Forth or BASIC or how I spent the 80s...
  • 85. 85 this social construct kills demons
  • 86. 86 this social construct kills demons
  • 87. 87 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 embedded 1999 systems 2000 2001 2002 2003 2004
  • 89. Kent Beck 89 eXtreme Programming the birth of agile Planning/feedback loops Release plan Code Iteration plan Acceptance test Stand-up meeting Pair negotiation Unit test Pair programming Months Weeks Days One day Hours Minutes Seconds By DonWells - Own work based on: XP-feedback.gif, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27448045
  • 90. Cultural traditions Analysis & synthesis Previous experiences New information Genetic heritage Decision (hypothesis) Observations Action (test) Unfolding interaction with environment Feedback Feedback Unfolding interaction with environment Act Decide Orient Observe Implicit guidance & control Feed forward Feed Feed forward forward Unfolding circumstances Outside information Implicit guidance & control John Boyd's OODA loop Feedback 90 it's war out there the OODA loop John Boyd
  • 91. Verification and Validation Project Definition Concept of Operations Requirements and Architecture Detailed Design Integration, Test, and Verification System Verification and Validation Operation and Maintenance Project Test and Integration Implementation Implementation Time 91 government mandated processes the v-model
  • 92. 92 software considerations in airborne systems and equipment certification RTCA DO-178B Level Failure condition Objectives[5] Failure Rate A Catastrophic 66 10−9/h B Hazardous 65 10−7/h C Major 57 10−5/h D Minor 28 10−3/h E No Effect 0 n/a
  • 93. 93 evolutionary prototyping the boehm spiral Plan next Phase Develop, verify next-level product Determine objectives, alternatives, constraints Evaluate alternatives identify, resolve risks Cummulative cost Review Commitment partition Risk analysis Risk analysis Risk analysis Prototype 1 Prototype 2 Prototype 3 Operational Prototype Risk analy- sis Requirements plan life-cycle plan Develop- ment plan Integration and test plan Concept of operation Simulations, models, benchmarks Software requirements Requirements validation Software product design Design validation and verification Detailed design Code Unit test Integration and test Acceptance test Implementation
  • 95. 95 once upon a time Romek Ellie
  • 96. 96 cryptography + physics = ??? we 🔬 digital identity
  • 97. 97 ● digital identity ● messaging ● privacy ● trust what we do IDENTITY & TRUST IN MONITORED SPACES THE VIRTUES OF PRIVACY BY DESIGN Eleanor McHugh Romek Szczesniak
  • 98. 98 ● ruby ● bash ● macOS ● golang ● crystal ● javascript how we do it
  • 99. 99 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" this is part of a proof of concept for a digital identity system it's part of a series of prototypes evolved from a series of pure BaSH scripts all the techniques demonstrated are applicable to any language with either quick compilation speed or fast interpreter launch like golang or ruby
  • 100. 100 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" Fair Use Exemptions Apply
  • 101. 101 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" bangs allow scripts to be executable
  • 102. 102 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" Environment Variables for configuration
  • 103. 103 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" Environment Variables for configuration
  • 104. 104 #!/bin/bash # (c) 2017 Innovative Identity Solutions Limited # all rights reserved # This script defines addresses for a service infrastructure baselined at $BASEPORT." # # Usage:" # export BASE_SERVICE=9000" # source infrastructure.sh" # PORT=$BASE_SERVICE_PORT ADDRESS=${SERVER_ADDRESS:=localhost} export DOMAIN_SERVICE=$PORT export DOMAIN_ADDRESS="$ADDRESS:$DOMAIN_SERVICE" let PORT++ export LOGGING_SERVICE=$PORT export LOGGING_ADDRESS="$ADDRESS:$LOGGING_SERVICE" let PORT++ export SECURE_STORE_SERVICE=$PORT export SECURE_STORE_ADDRESS="$ADDRESS:$SECURE_STORE_SERVICE" let PORT++ export REGISTRY_SERVICE=$PORT export REGISTRY_ADDRESS="$ADDRESS:$REGISTRY_SERVICE" let PORT++ export ORACLE_SERVICE=$PORT export ORACLE_ADDRESS="$ADDRESS:$ORACLE_SERVICE" let PORT++ export BEAR_SERVICE=$PORT export BEAR_ADDRESS="$ADDRESS:$BEAR_SERVICE" let PORT++ export VAL_SERVICE=$PORT export VAL_ADDRESS="$ADDRESS:$VAL_SERVICE" BASE_SERVICE_PORT=$DOMAIN_SERVICE Environment Variables for static configuration
  • 105. 105 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" command-line switches for instance variables
  • 106. 106 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" check for missing parameters
  • 107. 107 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" now for some Ruby magic
  • 108. 108 RUBY_DIR="$ROOT_DIR/ruby" source scripts/basics.sh # http_requests will print headers and response body along with stack dumps # if the env variable DEBUG_HTTP_REQUESTS exists ruby_web_client () { local program=$1 ruby -e " require 'json' require '$CLIENTS_DIR/web' $program " } http_request () { local version=$1 local method=$2 local address=$3 local endpoint=$4 local request_body=$5 ruby_web_client " if ENV['DEBUG_HTTP_REQUESTS'] response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req| puts 'REQUEST:' puts $request_body $request_body end puts 'RESPONSE:' response.each_header do |k, v| puts "#{k}: #{v}" end puts "body: #{response.body}" puts else WebClient.$method($version, '$address', endpoint = $endpoint) do |req| $request_body end rescue nil end " } where we keep our ruby scripts some handy Bash functions
  • 109. 109 DATA_DIR="$ROOT_DIR/data" COMMANDS_DIR="$ROOT_DIR/commands" MODELS_DIR="$ROOT_DIR/models" detect_wsl () { set -e grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null } UNIX_PROCESS_STARTUP_DELAY=1 WSL_PROCESS_STARTUP_DELAY=5 if detect_wsl ; then wait_for_process_launch () { sleep WSL_PROCESS_STARTUP_DELAY } else wait_for_process_launch () { sleep UNIX_PROCESS_STARTUP_DELAY } fi heading () { ruby -e " require '$COMMANDS_DIR/console' Console.heading '$1' " } subheading () { ruby -e " require '$COMMANDS_DIR/console' Console.subheading '$1' " } print_cic_statement() { ruby "$COMMANDS_DIR/cic_banner.rb" } finished () { heading "DONE" } useful directories
  • 110. 110 DATA_DIR="$ROOT_DIR/data" COMMANDS_DIR="$ROOT_DIR/commands" MODELS_DIR="$ROOT_DIR/models" detect_wsl () { set -e grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null } UNIX_PROCESS_STARTUP_DELAY=1 WSL_PROCESS_STARTUP_DELAY=5 if detect_wsl ; then wait_for_process_launch () { sleep WSL_PROCESS_STARTUP_DELAY } else wait_for_process_launch () { sleep UNIX_PROCESS_STARTUP_DELAY } fi heading () { ruby -e " require '$COMMANDS_DIR/console' Console.heading '$1' " } subheading () { ruby -e " require '$COMMANDS_DIR/console' Console.subheading '$1' " } print_cic_statement() { ruby "$COMMANDS_DIR/cic_banner.rb" } finished () { heading "DONE" } WSL can take a long time to launch a Linux process so we check for it and add a longer startup delay for our system to boot
  • 111. 111 DATA_DIR="$ROOT_DIR/data" COMMANDS_DIR="$ROOT_DIR/commands" MODELS_DIR="$ROOT_DIR/models" detect_wsl () { set -e grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null } UNIX_PROCESS_STARTUP_DELAY=1 WSL_PROCESS_STARTUP_DELAY=5 if detect_wsl ; then wait_for_process_launch () { sleep WSL_PROCESS_STARTUP_DELAY } else wait_for_process_launch () { sleep UNIX_PROCESS_STARTUP_DELAY } fi heading () { ruby -e " require '$COMMANDS_DIR/console' Console.heading '$1' " } subheading () { ruby -e " require '$COMMANDS_DIR/console' Console.subheading '$1' " } print_cic_statement() { ruby "$COMMANDS_DIR/cic_banner.rb" } finished () { heading "DONE" } each of these is a string containing Ruby code to be executed by the interpreter
  • 112. 112 RUBY_DIR="$ROOT_DIR/ruby" source scripts/basics.sh # http_requests will print headers and response body along with stack dumps # if the env variable DEBUG_HTTP_REQUESTS exists ruby_web_client () { local program=$1 ruby -e " require 'json' require '$CLIENTS_DIR/web' $program " } http_request () { local version=$1 local method=$2 local address=$3 local endpoint=$4 local request_body=$5 ruby_web_client " if ENV['DEBUG_HTTP_REQUESTS'] response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req| puts 'REQUEST:' puts $request_body $request_body end puts 'RESPONSE:' response.each_header do |k, v| puts "#{k}: #{v}" end puts "body: #{response.body}" puts else WebClient.$method($version, '$address', endpoint = $endpoint) do |req| $request_body end rescue nil end " } use local to give shell function parameters meaningful names
  • 113. 113 RUBY_DIR="$ROOT_DIR/ruby" source scripts/basics.sh # http_requests will print headers and response body along with stack dumps # if the env variable DEBUG_HTTP_REQUESTS exists ruby_web_client () { local program=$1 ruby -e " require 'json' require '$CLIENTS_DIR/web' $program " } http_request () { local version=$1 local method=$2 local address=$3 local endpoint=$4 local request_body=$5 ruby_web_client " if ENV['DEBUG_HTTP_REQUESTS'] response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req| puts 'REQUEST:' puts $request_body $request_body end puts 'RESPONSE:' response.each_header do |k, v| puts "#{k}: #{v}" end puts "body: #{response.body}" puts else WebClient.$method($version, '$address', endpoint = $endpoint) do |req| $request_body end rescue nil end " } shell variables are strings this allows us to pass in a ruby program as a string which will then be injected into this string as a text replacement
  • 114. 114 RUBY_DIR="$ROOT_DIR/ruby" source scripts/basics.sh # http_requests will print headers and response body along with stack dumps # if the env variable DEBUG_HTTP_REQUESTS exists ruby_web_client () { local program=$1 ruby -e " require 'json' require '$CLIENTS_DIR/web' $program " } http_request () { local version=$1 local method=$2 local address=$3 local endpoint=$4 local request_body=$5 ruby_web_client " if ENV['DEBUG_HTTP_REQUESTS'] response = WebClient.$method($version, '$address', endpoint = $endpoint) do |req| puts 'REQUEST:' puts $request_body $request_body end puts 'RESPONSE:' response.each_header do |k, v| puts "#{k}: #{v}" end puts "body: #{response.body}" puts else WebClient.$method($version, '$address', endpoint = $endpoint) do |req| $request_body end rescue nil end " } here we use it to make an HTTP call using our Ruby WebClient object
  • 115. 115 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" launch our service network
  • 116. 116 source scripts/ruby_web_api.sh if [ $# -ne 1 ]; then echo echo "This script launches an identity infrastructure baselined at the specified port address." echo echo "Usage:" echo " ./startup.sh base-port" exit 1 fi BASE_SERVICE_PORT=$1 source ./infrastructure.sh heading "Creating Service Infrastructure" echo " DOMAIN_ADDRESS = $DOMAIN_ADDRESS" echo " LOGGING_ADDRESS = $LOGGING_ADDRESS" echo " SECURE_STORE_ADDRESS = $SECURE_STORE_ADDRESS" echo " REGISTRY_ADDRESS = $REGISTRY_ADDRESS" echo " ORACLE_ADDRESS = $ORACLE_ADDRESS" echo " BEAR_ADDRESS = $BEAR_ADDRESS" echo " VAL_ADDRESS = $VAL_ADDRESS" create_registry launch_domain $DOMAIN_ADDRESS sleep 1 launch_service logging $LOGGING_ADDRESS launch_service secure_store $SECURE_STORE_ADDRESS launch_service registry $REGISTRY_ADDRESS launch_service oracle $ORACLE_ADDRESS
  • 117. 117 ROOT_DIR=`pwd` REGISTRY_DIR="$ROOT_DIR/registry" COMMANDS_DIR="$ROOT_DIR/commands" MODELS_DIR="$ROOT_DIR/models" create_registry () { subheading "create registry" rm -Rf "$REGISTRY_DIR" mkdir -p "$REGISTRY_DIR" pushd "$REGISTRY_DIR" ruby -e " require '$MODELS_DIR/oracle' require '$COMMANDS_DIR/encryption' Console.section 'Create $REGISTRY_DIR/Oracle.db' do oracle = Models::Oracle.new Console.section 'Create User Zero' do key = Encryption::create_rsa_key filename: 'keyzero.pem', save_to_disk: true digest = OpenSSL::Digest::SHA256.new(Base64.encode64 key.to_pem) oracle.keys.insert ID: 0, Label: '::1', Key: key.public_key.to_pem, Checksum: ENV['USE_AMALGALITE'] ? digest : digest.to_s Console.display_records oracle, :Keys end end " popd } create_user_database () { local database_dir="$REGISTRY_DIR/$1" local selfie="$ROOT_DIR/$2" heading "create user database: $database_dir" mkdir -p "$database_dir" pushd "$database_dir" ln -s "$REGISTRY_DIR/oracle.db" "$database_dir" ln -s "$selfie" "$database_dir" popd "$database_dir" } we can directly use Ruby's OpenSSL wrapper as well as our own API over that
  • 118. 118 ROOT_DIR=`pwd` REGISTRY_DIR="$ROOT_DIR/registry" COMMANDS_DIR="$ROOT_DIR/commands" MODELS_DIR="$ROOT_DIR/models" create_registry () { subheading "create registry" rm -Rf "$REGISTRY_DIR" mkdir -p "$REGISTRY_DIR" pushd "$REGISTRY_DIR" ruby -e " require '$MODELS_DIR/oracle' require '$COMMANDS_DIR/encryption' Console.section 'Create $REGISTRY_DIR/Oracle.db' do oracle = Models::Oracle.new Console.section 'Create User Zero' do key = Encryption::create_rsa_key filename: 'keyzero.pem', save_to_disk: true digest = OpenSSL::Digest::SHA256.new(Base64.encode64 key.to_pem) oracle.keys.insert ID: 0, Label: '::1', Key: key.public_key.to_pem, Checksum: ENV['USE_AMALGALITE'] ? digest : digest.to_s Console.display_records oracle, :Keys end end " popd } create_user_database () { local database_dir="$REGISTRY_DIR/$1" local selfie="$ROOT_DIR/$2" heading "create user database: $database_dir" mkdir -p "$database_dir" pushd "$database_dir" ln -s "$REGISTRY_DIR/oracle.db" "$database_dir" ln -s "$selfie" "$database_dir" popd "$database_dir" } we're also able to use SQLite via Amalgalite which compiles it as an in-process extension
  • 119. 119 #!/bin/bash # (c) 2018 Innovative Identity Solutions Limited # all rights reserved source scripts/ruby_web_api.sh print_cic_statement BASE_SERVICE_PORT=9000 source ./infrastructure.sh while getopts b:v:sh option do case "${option}" in h) echo echo "This script launches the infrastructure for user registration and interaction." echo "For each user and the oracle it creates a running web service." echo "It initialises the database when it runs." echo echo "Usage:" echo " ./demo.sh -b bearer-name -v validator-name" echo " ./demo.sh -h" echo " ./demo.sh -s" exit 0 ;; b) BEARER=${OPTARG};; v) VALIDATOR=${OPTARG};; s) shutdown $DOMAIN_ADDRESS;; esac done if [ -z ${BEARER+x} ]; then echo "specify bearer name with -b"; exit 1 fi if [ -z ${VALIDATOR+x} ]; then echo "specify validator name with -v"; exit 2 fi scripts/startup.sh $BASE_SERVICE_PORT heading "Launching bearer devices" launch_bearer $BEAR_SERVICE $BEARER "bear.jpg" launch_bearer $VAL_SERVICE $VALIDATOR "val.jpg" to create Ruby web services
  • 120. 120 source "$SCRIPTS_DIR/ruby_web_client.sh" launch_ruby_service () { local service=$1 local address=$2 local directory="$REGISTRY_DIR$3" local command_key=$4 pushd "$directory" ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" & wait_for_process_launch popd } launch_service () { local service=$1 local address=$2 local command_key=$3 local service_name="$service""_service" http_request :v1 post $DOMAIN_ADDRESS :A " req.set_form_data name: '$service_name', address: '$address'" launch_ruby_service "$service" "$address" "" "$command_key" } halt_service () { local version=$1 local address=$2 local command_key=$3 http_request :v1 shutdown $address nil "req.body = '$command_key'" } launch_bearer () { local port="$1" local name="$2" local selfie="$3" local command_key="$4" create_user_database "$name" "$selfie" pushd "$REGISTRY_DIR/$name" PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" & sleep 1 popd } we need this to make web requests
  • 121. 121 source "$SCRIPTS_DIR/ruby_web_client.sh" launch_ruby_service () { local service=$1 local address=$2 local directory="$REGISTRY_DIR$3" local command_key=$4 pushd "$directory" ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" & wait_for_process_launch popd } launch_service () { local service=$1 local address=$2 local command_key=$3 local service_name="$service""_service" http_request :v1 post $DOMAIN_ADDRESS :A " req.set_form_data name: '$service_name', address: '$address'" launch_ruby_service "$service" "$address" "" "$command_key" } halt_service () { local version=$1 local address=$2 local command_key=$3 http_request :v1 shutdown $address nil "req.body = '$command_key'" } launch_bearer () { local port="$1" local name="$2" local selfie="$3" local command_key="$4" create_user_database "$name" "$selfie" pushd "$REGISTRY_DIR/$name" PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" & sleep 1 popd } we can also start Ruby programs with dynamically set Environment Variables to configure them
  • 122. 122 source "$SCRIPTS_DIR/ruby_web_client.sh" launch_ruby_service () { local service=$1 local address=$2 local directory="$REGISTRY_DIR$3" local command_key=$4 pushd "$directory" ADDRESS="$address" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/$service""_service.rb" & wait_for_process_launch popd } launch_service () { local service=$1 local address=$2 local command_key=$3 local service_name="$service""_service" http_request :v1 post $DOMAIN_ADDRESS :A " req.set_form_data name: '$service_name', address: '$address'" launch_ruby_service "$service" "$address" "" "$command_key" } halt_service () { local version=$1 local address=$2 local command_key=$3 http_request :v1 shutdown $address nil "req.body = '$command_key'" } launch_bearer () { local port="$1" local name="$2" local selfie="$3" local command_key="$4" create_user_database "$name" "$selfie" pushd "$REGISTRY_DIR/$name" PORT="$port" COMMAND_KEY="$command_key" ruby "$SERVICES_DIR/bearer_service.rb" & sleep 1 popd } for each credential bearer in our system we can launch a custom ruby process in the background to handle their behaviour
  • 123. 123 known by their works Love is a poet, love sings the songs Pointing his fi nger you follow along Voices are calling, The monster wants out of you Paws you and claws you, you try not to fall - The Beast, Concrete Blonde
  • 124. 124 ● I have mixed feelings on patents ● I filed some, and selling the IP paid for several years of research ● it also means people can see what I do ● but the process can be complicated ● and many patents suck The Agony & The Ecstasy
  • 125. 125 ● original inventions ● not preexisting in nature - except biotech ● no maths - unless it's software and you're in the US ● must have a concrete implementation ● cannot have been published before What Can We Patent? Dell? Mac? WTF?!?!
  • 126. 126 ● inventors have to publish how their invention works - except Marconi? ● the patent provides a fixed term monopoly ● but the description of the invention is in the public domain ● only granted claims are enforceable Why Should We Patent? Nikola Tesla!