1+ process . title = "Basic.JS" ;
2+ const { parse_line, parse_line2} = require ( "./parser.js" ) ;
3+ const readline = require ( "readline-sync" ) ;
4+ const repl = require ( "repl" ) ;
5+ const code = [ ] , variables = { } , functions = {
6+ ABS ( args ) {
7+ const val = Math . abs ( replace_args ( args ) [ 0 ] ) ;
8+ if ( isNaN ( val ) ) throw new TypeError ( "INVALID VALUE" ) ;
9+ return val ;
10+ } ,
11+ CHAR ( args ) {
12+ const parsed_args = replace_args ( args ) ;
13+ let str = "" ;
14+ for ( const value of parsed_args ) {
15+ if ( typeof value != "number" ) throw new TypeError ( "INVALID VALUE" ) ;
16+ if ( value < 0 ) throw new RangeError ( "VALUE < 0" ) ;
17+ str += String . fromCharCode ( value ) ;
18+ }
19+ return str ;
20+ } ,
21+ ADD ( args ) {
22+ const parsed_args = replace_args ( args ) ;
23+ if ( typeof parsed_args [ 0 ] != "number" ) throw new TypeError ( "INVALID VALUE" ) ;
24+ if ( typeof parsed_args [ 1 ] != "number" ) throw new TypeError ( "INVALID VALUE" ) ;
25+ return parsed_args [ 0 ] + parsed_args [ 1 ] ;
26+ } ,
27+ SUB ( args ) {
28+ const parsed_args = replace_args ( args ) ;
29+ if ( typeof parsed_args [ 0 ] != "number" ) throw new TypeError ( "INVALID VALUE" ) ;
30+ if ( typeof parsed_args [ 1 ] != "number" ) throw new TypeError ( "INVALID VALUE" ) ;
31+ return parsed_args [ 0 ] - parsed_args [ 1 ] ;
32+ }
33+ } ;
34+ /**
35+ *
36+ * @param {any[] } args
37+ * @returns {string[] | number[] }
38+ */
39+ function replace_args ( args ) {
40+ let newArgs = [ ] ;
41+ for ( const val of args ) {
42+ if ( typeof val == "object" ) {
43+ if ( val . variable !== undefined ) {
44+ newArgs . push ( variables [ val . variable ] ) ;
45+ } else {
46+ newArgs . push ( functions [ val . functionName ] ( val . arguments ) ) ;
47+ }
48+ } else {
49+ newArgs . push ( val ) ;
50+ }
51+ }
52+ return newArgs ;
53+ }
54+ let lineNumber = 10 , interval , end , codeStr = { } ;
55+ function toCode ( str ) {
56+ const parsed = parse_line ( str ) ;
57+ code . push ( { line : parsed . line , instruction : parsed . instruction , arguments : parsed . arguments } ) ;
58+ }
59+ const instructions = {
60+ LET ( args ) {
61+ variables [ args [ 0 ] ] = args [ 1 ] ;
62+ } ,
63+ GOTO ( arg ) {
64+ lineNumber = arg ;
65+ } ,
66+ END ( ) {
67+ if ( ! end ) {
68+ return process . exit ( 0 ) ;
69+ }
70+ clearInterval ( interval ) ;
71+ end ?. ( ) ;
72+ end = undefined ;
73+ } ,
74+ LIST ( ) {
75+ for ( const key in codeStr ) {
76+ console . log ( `${ key } ${ codeStr [ key ] } ` ) ;
77+ }
78+ } ,
79+ PRINT ( args ) {
80+ if ( ! args ) throw new TypeError ( "NO ARGUMENTS" ) ;
81+ const pargs = replace_args ( args ) ;
82+ for ( const arg of pargs ) {
83+ if ( arg === undefined ) throw new TypeError ( "EMPTY VARIABLE" ) ;
84+ process . stdout . write ( arg . toString ( ) ) ;
85+ }
86+ console . log ( ) ;
87+ } ,
88+ HELP ( ) {
89+ console . log ( `LET KEY = VAL\nGOTO LINENUM\nEND\nLIST\nPRINT ...MESSAGE;\nHELP\nREM ...\nINPUT MSG;VAR...;\nRUN\nEDITOR\nASM\n!\nIF CHECK1 = CHECK2 THEN COMMAND\n\nADD(INT,INT)\nSUB(INT,INT)\nCHAR(INT...)\nABS(INT)` ) ;
90+ } ,
91+ REM ( ) { } ,
92+ INPUT ( args ) {
93+ if ( ! args ) throw new TypeError ( "NO ARGUMENTS" ) ;
94+ for ( const arg of args ) {
95+ if ( typeof arg != "object" ) {
96+ process . stdout . write ( arg ) ;
97+ } else {
98+ const val = readline . question ( "" ) ;
99+ variables [ arg . variable ] = val ;
100+ }
101+ }
102+ } ,
103+ RUN ( ) {
104+ return new Promise ( r => {
105+ lineNumber = code [ 0 ] ?. line ;
106+ if ( ! lineNumber ) {
107+ console . log ( "NO CODE." ) ;
108+ return r ( ) ;
109+ }
110+ end = r ;
111+ interval = setInterval ( step , 0 ) ;
112+ } ) ;
113+ } ,
114+ async EDITOR ( ) {
115+ await new Promise ( async r => {
116+ while ( true ) {
117+ const val = readline . question ( "EDITOR) " ) ;
118+ if ( val === "DONE" ) return r ( ) ;
119+ try {
120+ const parsed = parse_line ( val ) ;
121+ codeStr [ parsed . line ] = val . slice ( parsed . lineOffset ) ;
122+ } catch ( e ) {
123+ console . log ( e . message . toUpperCase ( ) ) ;
124+ }
125+ }
126+ } ) ;
127+ for ( const key in codeStr ) {
128+ console . log ( `${ key } ${ codeStr [ key ] } ` ) ;
129+ toCode ( `${ key } ${ codeStr [ key ] } ` ) ;
130+ }
131+ console . log ( "READY." ) ;
132+ } ,
133+ ASM ( ) {
134+ return new Promise ( r => {
135+ const server = repl . start ( ) ;
136+ server . once ( "exit" , ( ) => r ( ) ) ;
137+ } ) ;
138+ } ,
139+ IF ( args ) {
140+
141+ }
142+ } ;
143+ instructions [ "!" ] = instructions . ASM ;
144+ async function step ( ) {
145+ const index = code . findIndex ( c => c . line == lineNumber ) ;
146+ const instruction = code [ index ] ;
147+ const nextInstruction = code [ index + 1 ] ;
148+ lineNumber = nextInstruction ? nextInstruction . line : lineNumber ;
149+ await instructions [ instruction . instruction ] ( instruction . arguments ) ;
150+ if ( code . findIndex ( c => c . line == lineNumber ) < 0 ) {
151+ instructions . END ( ) ;
152+ }
153+ }
154+
155+ async function runOne ( str ) {
156+ const instruction = parse_line2 ( str ) ;
157+ await instructions [ instruction . instruction ] ( instruction . arguments ) ;
158+ }
159+
160+ console . log ( "BASIC.JS V1.0.0" ) ;
161+ ( async function ( ) {
162+ while ( true ) {
163+ const val = readline . question ( ") " ) ;
164+ if ( ! val ) continue ;
165+ try {
166+ await runOne ( val ) ;
167+ } catch ( e ) {
168+ console . log ( e . message . toUpperCase ( ) ) ;
169+ }
170+ }
171+ } ) ( ) ;
0 commit comments