-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathZBasic.zs
1426 lines (1206 loc) · 32.8 KB
/
ZBasic.zs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
OUTLINE and PREMISE
Z.BASIC - An interpreter that runs inside a quest that
facilitates a shell window that allows the player to
modify or write ad-hoc scripts while the game is running.
v.0.4.5
If function pointers were working, that'd be far simpler,
as I could enqueue instructions into main() in a quest script
In theory though, this would be a useful learning tool, as
the user could encode very small scripts live, and have the
quest execute them.
The syntax might be simplified, though.
It's the same premise as my TBA parser/interpreter, but with a
different scope.
It'd be a for loop.
When the user adds instructions, and closes the interpreter,
the instruction loop would be counted that'd be the loop operator.
Then the parser string matches the instruction and puts a value
onto a stack. Once done, a switch block would call instructions
based on the case values read from the stack
The switch block for those instructions would be huge:
One case per instruction in the engine, hence why *f() would be better.
It'd end up as some form of BASIC or Pascal, but the interface
wouldn't allow declaring vars, only using extant, predefined
vars.
Probably G0 through G1023, plus a set f 32 for each other
datatype. We'd probably need to count how many values are
set in the script, when the interpreter scans it, then store
each value into an array index.
The tricky part, is storing the 'current' vars passed to
instructions
Probably would just be the array index of each, plus a set of
temp vars in the parser to use for literals
It would be fun to construct it, but it would run at a fraction of the speed of ZScript
The parser would need to be able to store the values of
literals to an array, and track when they are used.
We'd need to keep a count of the last var used in the switch
block when processing instructions, and for each param,
we increment the count after passing the value:
e.g.
*/
const int TOP = 1024;
int STACK[TOP];
int popmem; //colds the value popped from any stack.
const int MAX_STACK_REG = TOP - 1;
//The array pointer to the stack in use.
int curstack;
void CurStack(int a) { curstack = a; }
int CurStack() { return curstack; }
int SP; //0 is NULL
int RIP; //0 is NULL, register pointer
int CV; //current global var
int CSR; //current script ram index
int CPV; //current param value
int CVT; //cur vaqr type
int CVV; //current var value
int CVL; //current vartype length
int EXP1; //Expr Accumulator 1
int EXP2; //Expr Accumulator 1
int INDX1; //misc 1
int ZBASIc[256]; //used for returning arrays.
ffc script stack
{
void run() {}
int top() { return TOP; }
int top(int a) { return SizeOfArray(a);; }
void change(int b) { curstack = b; SP = b[TOP]; }
void setCurStack(int b) { curstack = b; SP = b[TOP]; }
int maxSize()
{
c = curstack;
return ( SizeOfArray(c) - 1 );
}
void pop()
{
int c = curstack;
if ( c < 1 )
{
TraceNL(); TraceS"Invalid stack called by stack.pop: "; Trace(c);
return;
}
if ( isempty(c) )
{
TraceNL(); TraceS"Cannot pop from an empty stack. The empty stack was: "; Trace(c);
return;
}
popmem = c[TOP];
SP = --c[TOP];
//--c[TOP];
//SP = c[TOP];
}
void pop(int indx)
{
//RP = indx;
int c = curstack;
if ( c < 1 )
{
TraceNL(); TraceS"Invalid stack called by stack.pop: "; Trace(c);
return;
}
if ( isempty(c) )
{
TraceNL(); TraceS"Cannot pop from an empty stack. The empty stack was: "; Trace(c);
return;
}
indx = c[TOP];
SP = --c[TOP];
RIP = indx; //so, getSArg(RIP);
//--c[TOP];
//SP = c[TOP];
}
void push(int val)
{
int c = curstack;
if ( c < 1 )
{
TraceNL(); TraceS"Invalid stack called by stack.push: "; Trace(c);
return;
}
if ( isfull(c) )
{
TraceNL(); TraceS"Cannot push to a full stack. The full stack was: "; Trace(c);
return;
}
c[TOP] = val;
SP = ++c[TOP];
//++c[TOP];
//SP = c[TOP];
//DO WE HAVE = -- IN zsCRIPT YET (ASSIGN (DECREMENT FIRST ))??
}
bool isempty(int a) { return (!a[TOP]); }
bool isfull(int a) { return ( a[TOP] >= MAX_STACK_REG ); }
void init(int a) { for ( int q = 0; q < TOP; ++q ) { a[q] = 0; }
}
int VARTYPES[TOP]; //0 is null. First valid memory index == 1
int count = 0; //the current index for storing or reading back variables when executing stack calls
int G[256];
int I[256];
ffc F[256];
npc N[256];
eweapon E[256];
lweapon L[256];
item IT[256];
itemdata ID[256];
npcdata ND[256];
spritedata WD[256];
combodata CD[256];
shopdata SD[256];
mapdata MD[256];
int WORD[64]; //HOLDS THHE CURRENT COMMAND
int PARAM[13]; //11 + sign + dot
int VARIABLE[7]; //type_id + 4 digits
int PARAMS[256];
int STACK[256]; //instruction IDs
int OPERAND[1024];
int OPERATOR[1024];
//maths
int operator_type; //current operator
const int TYPE_NULL = 0;
const int TYPE_GLOBAL = 1;
const int TYPE_INT = 2;
const int TYPE_NPC = 3;
const int TYPE_LWEAPON = 4;
const int TYPE_EWEAPON = 5;
const int TYPE_FFC = 6;
const int TYPE_ITEM = 7;
const int TYPE_ITEMDATA = 8;
const int TYPE_NPCDATA = 9;
const int TYPE_COMBODATA = 10;
const int TYPE_SPRITEDATA = 11;
const int TYPE_SHOPDATA = 12;
const int TYPE_MAPDATA = 13;
void RunInstruction()
{
switch(STACK[SP])
{
case FASTTILE:
{
Screen->FastTile(GetArg(), GetArg(), GetArg(), GetArg(), GetArg(), GetArg());
break;
}
}
}
//Advances a line in the instruction list.
// CR(list[q], 64)
// q = CR(q,64);
int CR(int pos, int linewidth)
{
return pos - pos%linewidth + linewidth;
int GetArg()
{
int indx = count;
CVT = VARTYPES[count];
++count;
int rv;
switch(CVT) //which array to use
{
case TYPE_GLOBAL;
{
rv = G[indx]; break;
}
case TYPE_INT:
{
rv = I[indx]; break;
}
case TYPE_NPC:
{
rv = N[indx]; break;
}
case TYPE_LWEAPON:
{
rv = L[indx]; break;
}
case TYPE_EWEAPON:
{
rv = E[indx]; break;
}
case TYPE_FFC:
{
rv = F[indx]; break;
}
case TYPE_ITEM:
{
rv = IT[indx]; break;
}
case TYPE_ITEMDATA:
{
rv = ID[indx]; break;
}
case TYPE_NPCDATA:
{
rv = ND[indx]; break;
}
case TYPE_COMBODATA:
{
rv = CD[indx]; break;
}
case TYPE_SPRITEDATA:
{
rv = WD[indx]; break;
}
case TYPE_SHOPDATA:
{
rv = SD[indx]; break;
}
case TYPE_MAPDATA:
{
rv = MD[indx]; break;
}
default:
{
TraceS("Invalid datatype supplied to GetArg()");
break;
}
}
return rv;
}
//sets the arg value to any type of array
void SetArg(int val)
{
int indx = count;
CVT = VARTYPES[count];
++count;
int rv;
switch(CVT) //which array to use
{
case TYPE_GLOBAL;
{
G[indx] = Untype(val) = Untype(val); break;
}
case TYPE_INT:
{
I[indx] = Untype(val); break;
}
case TYPE_NPC:
{
N[indx] = Untype(val); break;
}
case TYPE_LWEAPON:
{
L[indx] = Untype(val); break;
}
case TYPE_EWEAPON:
{
E[indx] = Untype(val); break;
}
case TYPE_FFC:
{
F[indx] = Untype(val); break;
}
case TYPE_ITEM:
{
IT[indx] = Untype(val); break;
}
case TYPE_ITEMDATA:
{
ID[indx] = Untype(val); break;
}
case TYPE_NPCDATA:
{
ND[indx] = Untype(val); break;
}
case TYPE_COMBODATA:
{
CD[indx] = Untype(val); break;
}
case TYPE_SPRITEDATA:
{
WD[indx] = Untype(val); break;
}
case TYPE_SHOPDATA:
{
SD[indx] = Untype(val); break;
}
case TYPE_MAPDATA:
{
MD[indx] = Untype(val); break;
}
default:
{
TraceS("Invalid datatype supplied to GetArg()");
break;
}
}
}
//NEWER functions to extract a var value from a token.
//gets the array ID (type) and index ID of the array
int _GetVar(int token, int pos) if ( IdentifyVar(token,0)) return GetVarValue(); return 0; }
int IdentifyVar(int w, int pos)
{
int v[5]; //varid[3]; 1024
int type[3]; //type 2
int len = strlen(w)-1;
if ( len > 7 ) return false;
int temp = CVL;
int vartype;
//copy only the type to this array
for ( ; temp <= len; ++temp )
{
if ( IsNumber(w[temp]) )
{
v[temp] = w[temp];
continue;
}
if ( IsAlpha(w[temp]) )
{
v[temp] = w[temp];
continue;
}
}
if ( strcmp(v, "G") ) vartype = TYPE_GLOBAL;
else if ( strcmp(v, "I") ) vartype = TYPE_INT;
else if ( strcmp(v, "N") ) vartype = TYPE_NPC;
else if ( strcmp(v, "L") ) vartype = TYPE_LWEAPON;
else if ( strcmp(v, "E") ) vartype = TYPE_EWEAPON;
else if ( strcmp(v, "F") ) vartype = TYPE_FFC;
else if ( strcmp(v, "IT") ) vartype = TYPE_ITEM;
else if ( strcmp(v, "ID") ) vartype = TYPE_ITEMDATA;
else if ( strcmp(v, "ND") ) vartype = TYPE_NPCDATA;
else if ( strcmp(v, "CD") ) vartype = TYPE_COMBODATA;
else if ( strcmp(v, "WD") ) vartype = TYPE_SPRITEDATA;
else if ( strcmp(v, "SD") ) vartype = TYPE_SHOPDATA;
else if ( strcmp(v, "MD") ) vartype = TYPE_MAPDATA;
else { vartype = TYPE_WTF; TraceNL(); TracS("Illegal vartype found by IdentifyVar()"); return false;}
CVL = 0; //clear
int id = itoa(v);
ZBASIC[0] = vartype; ZBASIC[1] = id;
return true;
}
int GetVarValue();
{ int type = ZBASIC[0];
int indx = ZBASIC[1];
int rv;
switch(type) //which array to use
{
case TYPE_GLOBAL;
{
rv = G[indx]; break;
}
case TYPE_INT:
{
rv = I[indx]; break;
}
case TYPE_NPC:
{
rv = N[indx]; break;
}
case TYPE_LWEAPON:
{
rv = L[indx]; break;
}
case TYPE_EWEAPON:
{
rv = E[indx]; break;
}
case TYPE_FFC:
{
rv = F[indx]; break;
}
case TYPE_ITEM:
{
rv = IT[indx]; break;
}
case TYPE_ITEMDATA:
{
rv = ID[indx]; break;
}
case TYPE_NPCDATA:
{
rv = ND[indx]; break;
}
case TYPE_COMBODATA:
{
rv = CD[indx]; break;
}
case TYPE_SPRITEDATA:
{
rv = WD[indx]; break;
}
case TYPE_SHOPDATA:
{
rv = SD[indx]; break;
}
default:
{
rv = 0;
TraceNL();
TraceS("GetVarValue() encountered an invalid var array type");
TraceNL();
break
}
}
ZBASIC[0] = 0;
ZBASIC[1] = 0;
return rv;
}
//this stores the ID when lexing. Parsing uses the literal stored to the script RAM.
//We could store this directly on the stack, but I would rather have 100 scripts with 1024 max
//instructions each, that we can copy to the stack when they run.
//but then, we would need a mechanism to store al of the values used by scripts when they complete execution.
//Grr... That'd be faster, but it would eat quite a lot of array space.
//Otherwise, we interpret the scripts each time before execution. No JIT here. :P
int GetInstruction(int word)
{
/* Would it be faster to do an incremental pattern match?
//Probably not?
int wordsize = strlen(word);
int words[]=
{
list each command one at time
each on its own line
shortest to longest.
pattern match begins at a specified word size?
}
*/
if ( strcmp(word, "FastTile" ) return FASTTILE;
}
//determines the type of array to use
int ExtractVarType(int w)
{
/*
int types[]=
"
G //global
I //int
N //npc
L //lweapon
E //eweapon
It //item
F //ffc
ID //itemdata
ND //npcdata
CD //combodata
WD //spritedata
SD //shopdata
MD //mapdata
";
*/
int v[3]; //vartype[3];
int len = strlen(w)-1;
int temp;
//copy only the type to this array
for ( ; temp < 2; ++temp )
{
if ( !IsNumber(w[temp]) )
{
v[temp] = w[temp];
}
}
CVL = temp; //set the length of this var,
//we'll need it for speeding uo extracting its
//literal value
if ( strcmp(v, "G") ) return TYPE_GLOBAL;
if ( strcmp(v, "I") ) return TYPE_INT;
if ( strcmp(v, "N") ) return TYPE_NPC;
if ( strcmp(v, "L") ) return TYPE_LWEAPON;
if ( strcmp(v, "E") ) return TYPE_EWEAPON;
if ( strcmp(v, "F") ) return TYPE_FFC;
if ( strcmp(v, "IT") ) return TYPE_ITEM;
if ( strcmp(v, "ID") ) return TYPE_ITEMDATA;
if ( strcmp(v, "ND") ) return TYPE_NPCDATA;
if ( strcmp(v, "CD") ) return TYPE_COMBODATA;
if ( strcmp(v, "WD") ) return TYPE_SPRITEDATA;
if ( strcmp(v, "SD") ) return TYPE_SHOPDATA;
if ( strcmp(v, "MD") ) return TYPE_MAPDATA;
I //item
F //ffc
ID //itemdata
ND //npcdata
CD //combodata
WD //spritedata
SD //shopdata
}
//gets the index ID of the array
int ExtractVarID(int w)
{
int v[5]; //vartype[3];
int len = strlen(w)-1;
int temp = CVL;
//copy only the type to this array
for ( ; temp <= len; ++temp )
{
if ( IsNumber(w[temp]) )
{
v[temp] = w[temp];
}
}
CVL = 0; //clear
int id = itoa(v);
return id;
}
//determines the type of array to use
int ExtractVarType(int w)
{
/*
int types[]=
"
G //global
I //int
N //npc
L //lweapon
E //eweapon
It //item
F //ffc
ID //itemdata
ND //npcdata
CD //combodata
WD //spritedata
SD //shopdata
MD //mapdata
";
*/
int v[3]; //vartype[3];
int len = strlen(w)-1;
int temp;
//copy only the type to this array
for ( ; temp < 2; ++temp )
{
if ( !IsNumber(w[temp]) )
{
v[temp] = w[temp];
}
}
CVL = temp; //set the length of this var,
//we'll need it for speeding uo extracting its
//literal value
if ( strcmp(v, "G") ) return TYPE_GLOBAL;
if ( strcmp(v, "I") ) return TYPE_INT;
if ( strcmp(v, "N") ) return TYPE_NPC;
if ( strcmp(v, "L") ) return TYPE_LWEAPON;
if ( strcmp(v, "E") ) return TYPE_EWEAPON;
if ( strcmp(v, "F") ) return TYPE_FFC;
if ( strcmp(v, "IT") ) return TYPE_ITEM;
if ( strcmp(v, "ID") ) return TYPE_ITEMDATA;
if ( strcmp(v, "ND") ) return TYPE_NPCDATA;
if ( strcmp(v, "CD") ) return TYPE_COMBODATA;
if ( strcmp(v, "WD") ) return TYPE_SPRITEDATA;
if ( strcmp(v, "SD") ) return TYPE_SHOPDATA;
if ( strcmp(v, "MD") ) return TYPE_MAPDATA;
I //item
F //ffc
ID //itemdata
ND //npcdata
CD //combodata
WD //spritedata
SD //shopdata
}
int GetVarValue(int type, int indx);
{
int rv;
switch(type) //which array to use
{
case TYPE_GLOBAL;
{
rv = G[indx]; break;
}
case TYPE_INT:
{
rv = I[indx]; break;
}
case TYPE_NPC:
{
rv = N[indx]; break;
}
case TYPE_LWEAPON:
{
rv = L[indx]; break;
}
case TYPE_EWEAPON:
{
rv = E[indx]; break;
}
case TYPE_FFC:
{
rv = F[indx]; break;
}
case TYPE_ITEM:
{
rv = IT[indx]; break;
}
case TYPE_ITEMDATA:
{
rv = ID[indx]; break;
}
case TYPE_NPCDATA:
{
rv = ND[indx]; break;
}
case TYPE_COMBODATA:
{
rv = CD[indx]; break;
}
case TYPE_SPRITEDATA:
{
rv = WD[indx]; break;
}
case TYPE_SHOPDATA:
{
rv = SD[indx]; break;
}
}
return rv;
}
//stores an instruction string into WORD[] when parsing the script,
int GetInstrString(int word)
{
int buf[64];
int sz = strlen(word) -1;
int temp; bool n; bool token; int q; int paramID;
for ( ; temp < sz; ++temp )
{
//if we find a token before an instruction, exit and report false?
if ( IsParsingToken(word[q]) continue; //return 0; //break;
//! ...but we need to store tokens onto their own tempstack!!
if ( IsNumber(word[q]) ) continue; //ignore line numbers and all numerals
if ( word[q] == ' ' ) continue; //eat WS
if ( !word[q] ) break; //halt on str term.
buf[q] = word[q];
}
for ( q = 0; q < 64; ++q )
{
//tore label into the global word buffer.
WORD[q] = buf[q];
}
//! Here we must also store the param values, or any assigns.
//Find the instruction parame
// We continue to scan, starting at temp:
int param[64]; int scope;
do
{
for ( ; temp < sz; ++temp )
{
if ( word[temp] == ' ' ) continue; //eat WS
//open scope and copy
if ( word[temp] == '(' )
{
do
{
++temp;
if ( word[temp] == ' ' ) continue; //eat WS
if ( word[temp] == '(' )
{
++scope;
continue;
}
if ( word[temp] == ')'
{
--scope;
continue;
}
param[temp] = word[temp];
}
while(scope <= 0);
}
//determine if param is an expression
//if it is:
//1. Copy it to the EXPRESSION array.
//2 resolve i
//store its litral value
//id not, it's a var or a literal
//extract the vallue and move on
//inrement param, so that we can know how many of them we store
//is this at all useful?
++paramID;
SetArg(atof(param)); //param must be resolved if an expression, so we might need another buffer
}
while(word[temp] != ';'); //look for the next param, or $END
}
/*
This also needs to be in the expression checker.
Assigns in the language will be enclosed by braces or parens
or some special token.
[I26 = 90;]
Do we need array sntax?
This way, the parser knows that it is about to encounter a variable?
//or shyould we just enclose variables?
Perhaps @var_id?
@G26 = 70
One positive note, is that assign and expr during a function call would work.
*/
}
float ExpressionChecker(int word)
{
int rv;
//convert vars to literals and store
//store script literals and store
//store operation signs
//determine operation ordering
//resolvng scopes
//process expression
//Functions aere in the fake ffc 'class' expr.
//call as expr.f()
return rv;
}
void Parse()
{
int inistack = curstack;
SP = 0;
//scan each line
//prune line number
prune leading spaces
//store the text of this line until '(' or 'other tokenm,
//such as '=' to WORD[]
if the operator is a maths sign, or a token
that modifies a var immediately
UPDATE GLOBAL VARS
then do the maths here
store the param:
1. if a literal, copy the char to PARAM
then
CPV = ftoa(PARAM);
2. otherwise, it's a var:
read the identifier to VARIABLE[]
scan the type ID first
//nO, SCREW THAT.
//Use an UNTYPED array, and we won't need to care about datatypes!
Otherwise...
CVT = ExtractVarType(PARAM);
VARTYPES[CSR] = CVT;
//extract the param *value* next
//SCRIPTRAM[CSR] = ;
SetArg(CVT,GetvarValue(CVT,ExtractVarID(PARAM)));
//now the value of that variable is set and ready to execute
//with Getparam().
repeat for next param.
run :
++SP; STACK[SP] = GetInstruction(WORD);
}
/*
THis wuld allow for truly generic processing of instructions.
Any internal instruction would simply use getArg() to get
the value assignd to it.
The parser would not know if there are insufficient parameters
aimed at an instruction, but we could determine this during lexing...
The user could assign values to these, and a set of predefined
scripts to edit.
/*
//Expressions
/*
1. While there are still tokens to be read in,
1.1 Get the next token.
1.2 If the token is:
1.2.1 A number: push it onto the value stack.
1.2.2 A variable: get its value, and push onto the value stack.
1.2.3 A left parenthesis: push it onto the operator stack.
1.2.4 A right parenthesis:
1 While the thing on top of the operator stack is not a
left parenthesis,
1 Pop the operator from the operator stack.
2 Pop the value stack twice, getting two operands.
3 Apply the operator to the operands, in the correct order.
4 Push the result onto the value stack.
2 Pop the left parenthesis from the operator stack, and discard it.
1.2.5 An operator (call it thisOp):
1 While the operator stack is not empty, and the top thing on the
operator stack has the same or greater precedence as thisOp,
1 Pop the operator from the operator stack.
2 Pop the value stack twice, getting two operands.
3 Apply the operator to the operands, in the correct order.
4 Push the result onto the value stack.
2 Push thisOp onto the operator stack.
2. While the operator stack is not empty,
1 Pop the operator from the operator stack.
2 Pop the value stack twice, getting two operands.
3 Apply the operator to the operands, in the correct order.
4 Push the result onto the value stack.
3. At this point the operator stack should be empty, and the value
stack should have only one value in it, which is the final result.
*/
ffc script expr
{
void run(){}
//int precedence(int op) { return Precedence(op); }
//int applyOp(int a, int b, int op) { return ApplyOp(a, b, op); }
// Function to find precedence of
// operators.
int Precedence(int op)
{
if (op == '+') return 1;
if ( op == '-') return 1;
if (op == '*') return 2;
if ( op == '/') return 2;
if ( op }== '^') return 3;
return 0;
}
// Function to perform arithmetic operations.
int ApplyOp(int a, int b, int op){
switch(op)
{
case '+': { return a + b; }
case '-': { return a - b; }
case '*': { return a * b; }
case '/': { return a / b; }
case '^'; { return Pow(a,b); } //No bitwise Xor in Z.Basic.
}
}
}
/* Parens
Parens increase precedence by ++ per paren.
Work similar to scope in other functions.
*/
int FindScopePrecedence(int token, int pos)
{
int len = strlen(token);
int scope; int tempscope;
do
{
if ( token[pos] == '(' ) { ++scope; ++tempscope;