From 9d2a57e7bdd631f38cc3e0af9cb1484ff91711f0 Mon Sep 17 00:00:00 2001 From: Florent Madelaine Date: Mon, 22 Jan 2024 09:02:25 +0100 Subject: [PATCH] MVaP en javascript --- MVaP/MVaP-v0/MVaP/index.html | 72 ++++++ MVaP/MVaP-v0/MVaP/js/CBaP.js | 216 +++++++++++++++++ MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot | 33 +++ MVaP/MVaP-v0/MVaP/js/LexerMVaP.png | Bin 0 -> 73986 bytes MVaP/MVaP-v0/MVaP/js/MVaP.js | 374 +++++++++++++++++++++++++++++ MVaP/MVaP-v0/MVaP/js/Pile.js | 153 ++++++++++++ 6 files changed, 848 insertions(+) create mode 100644 MVaP/MVaP-v0/MVaP/index.html create mode 100644 MVaP/MVaP-v0/MVaP/js/CBaP.js create mode 100644 MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot create mode 100644 MVaP/MVaP-v0/MVaP/js/LexerMVaP.png create mode 100644 MVaP/MVaP-v0/MVaP/js/MVaP.js create mode 100644 MVaP/MVaP-v0/MVaP/js/Pile.js diff --git a/MVaP/MVaP-v0/MVaP/index.html b/MVaP/MVaP-v0/MVaP/index.html new file mode 100644 index 0000000..7b40946 --- /dev/null +++ b/MVaP/MVaP-v0/MVaP/index.html @@ -0,0 +1,72 @@ + + + + + MVàP + + + + + + + + +

Machine Virtuelle à Pile

+ +

Historique

+ Blabla sur la MVàP... + +

Documentation

+ Toute la doc +

+ lorem ipsum +

La MVàP

+

Entrez le code

+
+ +
+ +

Exécution

+ + + + + + + + + +
+
+    
+
+ + + + diff --git a/MVaP/MVaP-v0/MVaP/js/CBaP.js b/MVaP/MVaP-v0/MVaP/js/CBaP.js new file mode 100644 index 0000000..9864c57 --- /dev/null +++ b/MVaP/MVaP-v0/MVaP/js/CBaP.js @@ -0,0 +1,216 @@ +/** + * Code Binaire pour Machine Virtuelle à Pile. + * Les flottants sont des double qui prennent la place de 2 ints. + * Les adresses sont des int. + * CALL empile l'adresse de retour et la vauler du framePointer dans la pile. + */ +public class CBaP { + + + + pc = 0; + fp = 0; + stack; + program; + const SizeofDouble = 2; + + _debug = false; + + CBaP(program, debug, stackSize) { + this.program = program; + this._debug = debug; + this.stack = new Pile(stackSize); + } + + dumpInstruction(ii, out) { + let i = ii; + switch(program.get_int(i)) { + case AssembleMVaP.ADD: out.print("ADD "); break; + case AssembleMVaP.SUB: out.print("SUB "); break; + case AssembleMVaP.MUL: out.print("MUL "); break; + case AssembleMVaP.DIV: out.print("DIV "); break; + case AssembleMVaP.INF: out.print("INF "); break; + case AssembleMVaP.INFEQ: out.print("INFEQ "); break; + case AssembleMVaP.SUP: out.print("SUP "); break; + case AssembleMVaP.SUPEQ: out.print("SUPEQ "); break; + case AssembleMVaP.EQUAL: out.print("EQUAL "); break; + case AssembleMVaP.NEQ: out.print("NEQ "); break; + + case AssembleMVaP.FADD: out.print("FADD "); break; + case AssembleMVaP.FSUB: out.print("FSUB "); break; + case AssembleMVaP.FMUL: out.print("FMUL "); break; + case AssembleMVaP.FDIV: out.print("FDIV "); break; + case AssembleMVaP.FINF: out.print("FINF "); break; + case AssembleMVaP.FINFEQ: out.print("FINFEQ"); break; + case AssembleMVaP.FSUP: out.print("FSUP "); break; + case AssembleMVaP.FSUPEQ: out.print("FSUPEQ"); break; + case AssembleMVaP.FEQUAL: out.print("FEQUAL"); break; + case AssembleMVaP.FNEQ: out.print("FNEQ "); break; + case AssembleMVaP.ITOF: out.print("ITOF "); break; + case AssembleMVaP.FTOI: out.print("FTOI "); break; + + case AssembleMVaP.RETURN: out.print("RETURN"); break; + case AssembleMVaP.POP: out.print("POP "); break; + case AssembleMVaP.READ: out.print("READ "); break; + case AssembleMVaP.WRITE: out.print("WRITE "); break; + case AssembleMVaP.WRITEF: out.print("WRITEF"); break; + case AssembleMVaP.PADD: out.print("PADD "); break; + case AssembleMVaP.PUSHGP: out.print("PUSHGP"); break; + case AssembleMVaP.PUSHFP: out.print("PUSHFP"); break; + case AssembleMVaP.DUP: out.print("DUP "); break; + + case AssembleMVaP.PUSHI: out.print("PUSHI "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.PUSHG: out.print("PUSHG "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.STOREG: out.print("STOREG"); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.PUSHL: out.print("PUSHL "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.STOREL: out.print("STOREL"); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.PUSHR: out.print("PUSHR "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.STORER: out.print("STORER"); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.FREE: out.print("FREE "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.ALLOC: out.print("ALLOC "); out.format("%7d ", program.get_int(++i)); break; + + case AssembleMVaP.PUSHF: out.print("PUSHF "); ++i; out.format("%7.3f ", program.get_double(++i)); break; + + case AssembleMVaP.JUMP: out.print("JUMP "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.JUMPF: out.print("JUMPF "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.JUMPI: out.print("JUMPI "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.CALL: out.print("CALL "); out.format("%7d ", program.get_int(++i)); break; + case AssembleMVaP.HALT: out.print("HALT "); break; + default: System.err.println("Code inconnu "+program.get_int(i)+" ligne "+i); + } + if (i == ii) out.print(" "); + return i; + } + + public void dumpProgram(PrintStream out) { + // out.println(program.toString(true)); + // out.println(program.toString()); + out.println(" Adr | Instruction"); + out.println("-----+---------------"); + for(int i = 0; i < program.getSize(); i++) { + out.format("%4d | ", i); + i = dumpInstruction(i, out); + out.println(); + } + } + + private void _call(int label) { + push(pc+1); + push(fp); + fp = size(); + pc = label; + } + + private void _return() { + while(size() > fp) + pop(); + fp = pop(); + pc = pop(); + } + + private BufferedReader input = null; + private int _read() { + try { + if (input == null) + input = new BufferedReader(new InputStreamReader(System.in)); + return Integer.parseInt(input.readLine()); + } catch (Exception e) { + System.err.println(e); + System.exit(1); + return 0; + } + } + + public boolean execute() { + if (_debug) { + dumpProgram(System.out); + System.err.println(); + System.err.println(" pc | | fp pile"); + System.err.println("===================================================="); + } + pc = 0; + while (true) { + if (_debug) { + System.err.format("%4d | ", pc); + dumpInstruction(pc, System.err); + System.err.format("| %4d %s\n", fp, stack.toString()); + } + try { + int p1, p2; // utile pour être sûr de l'ordre des pop() ! + double d1, d2; + switch(program.get_int(pc++)) { + case AssembleMVaP.ADD: p1 = pop(); p2 = pop(); push(p2 + p1); break; + case AssembleMVaP.SUB: p1 = pop(); p2 = pop(); push(p2 - p1); break; + case AssembleMVaP.MUL: p1 = pop(); p2 = pop(); push(p2 * p1); break; + case AssembleMVaP.DIV: p1 = pop(); p2 = pop(); push(p2 / p1); break; + case AssembleMVaP.INF: p1 = pop(); p2 = pop(); push(p2 < p1 ? 1 : 0); break; + case AssembleMVaP.INFEQ: p1 = pop(); p2 = pop(); push(p2 <= p1 ? 1 : 0); break; + case AssembleMVaP.SUP: p1 = pop(); p2 = pop(); push(p2 > p1 ? 1 : 0); break; + case AssembleMVaP.SUPEQ: p1 = pop(); p2 = pop(); push(p2 >= p1 ? 1 : 0); break; + case AssembleMVaP.EQUAL: p1 = pop(); p2 = pop(); push(p2 == p1 ? 1 : 0); break; + case AssembleMVaP.NEQ: p1 = pop(); p2 = pop(); push(p2 != p1 ? 1 : 0); break; + + case AssembleMVaP.FADD: d1 = pop_double(); d2 = pop_double(); push(d2 + d1); break; + case AssembleMVaP.FSUB: d1 = pop_double(); d2 = pop_double(); push(d2 - d1); break; + case AssembleMVaP.FMUL: d1 = pop_double(); d2 = pop_double(); push(d2 * d1); break; + case AssembleMVaP.FDIV: d1 = pop_double(); d2 = pop_double(); push(d2 / d1); break; + case AssembleMVaP.FINF: d1 = pop_double(); d2 = pop_double(); push(d2 < d1 ? 1 : 0); break; + case AssembleMVaP.FINFEQ: d1 = pop_double(); d2 = pop_double(); push(d2 <= d1 ? 1 : 0); break; + case AssembleMVaP.FSUP: d1 = pop_double(); d2 = pop_double(); push(d2 > d1 ? 1 : 0); break; + case AssembleMVaP.FSUPEQ: d1 = pop_double(); d2 = pop_double(); push(d2 >= d1 ? 1 : 0); break; + case AssembleMVaP.FEQUAL: d1 = pop_double(); d2 = pop_double(); push(d2 == d1 ? 1 : 0); break; + case AssembleMVaP.FNEQ: d1 = pop_double(); d2 = pop_double(); push(d2 != d1 ? 1 : 0); break; + + case AssembleMVaP.FTOI: push((int)pop_double()); break; + case AssembleMVaP.ITOF: push((double)pop()); break; + + case AssembleMVaP.RETURN: _return(); break; + case AssembleMVaP.POP: pop(); break; + case AssembleMVaP.READ: push(_read()); break; + case AssembleMVaP.WRITE: System.out.format("%7d\n", peek()); break; + case AssembleMVaP.WRITEF: System.out.format("%7.3f\n", peek_double()); break; + case AssembleMVaP.PADD: p1 = pop(); p2 = pop(); push(p2 + p1); break; + case AssembleMVaP.PUSHGP: push(0); break; + case AssembleMVaP.PUSHFP: push(fp); break; + case AssembleMVaP.DUP: push(peek()); break; + + case AssembleMVaP.PUSHI: push(program.get_int(pc++)); break; + case AssembleMVaP.PUSHG: push(get(program.get_int(pc++))); break; + case AssembleMVaP.STOREG: set(program.get_int(pc++), pop()); break; + // ajouter -2 si adresse négative ? + case AssembleMVaP.PUSHL: push(get(fp+program.get_int(pc++))); break; + case AssembleMVaP.STOREL:set(fp+program.get_int(pc++), pop()); break; + case AssembleMVaP.PUSHR: push(get(pop()+program.get_int(pc++)));break; + case AssembleMVaP.STORER:p1 = pop(); p2 = pop(); set(p2+program.get_int(pc++), p1); break; + case AssembleMVaP.FREE: doPop(program.get_int(pc++)); break; + case AssembleMVaP.ALLOC: doPush(program.get_int(pc++)); break; + + case AssembleMVaP.PUSHF: push(program.get_int(pc++)); push(program.get_int(pc++)); break; + + case AssembleMVaP.JUMP: pc = program.get_int(pc); break; + case AssembleMVaP.JUMPF: if (pop() == 0) pc = program.get_int(pc); else pc++; break; + case AssembleMVaP.JUMPI: pc = program.get_int(pc)+pop(); break; + case AssembleMVaP.CALL: _call(program.get_int(pc)); break; + case AssembleMVaP.HALT: return true; + default: System.err.println("Code inconnu "+program.get_int(pc)+" ligne "+pc); return false; + } + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println(stack.getException()); + return false; + } + } + } + + void push(int i) { stack.push(i); } + int pop() { return stack.pop_int(); } + void push(double d) { stack.push(d); } + double pop_double() { return stack.pop_double(); } + int peek() { return stack.peek_int(); } + double peek_double() { return stack.peek_double(); } + int size() { return stack.getSize(); } + void set(int index, int i) { stack.set(index, i); } + int get(int index) { return stack.get_int(index); } + + void doPop(int nb) { for(; nb > 0; nb--) stack.pop_int(); } + void doPush(int nb) { for(; nb > 0; nb--) stack.push(0); } +} diff --git a/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot new file mode 100644 index 0000000..be9c7c5 --- /dev/null +++ b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot @@ -0,0 +1,33 @@ +digraph LexerMVaP { + Start -> Start [label="space "]; + Start -> Id [label="[A-Z]"]; + Id -> Id [label="[A-Z]"]; + + Start -> Int [label="[-+0-9]"]; + Int -> Int [label="[0-9]"]; + Int -> Decimal [label="."]; + Int -> E [label="E"]; + + Decimal -> Decimal [label="[0-9]"]; + Decimal -> E [label="E"]; + + E -> Exponent [label="[-+0-9]"]; + Exponent -> Exponent [label="[0-9]"]; + + Start -> error [label="*"]; + Id -> error [label="*"]; + Int -> error [label="*"]; + Decimal -> error [label="*"]; + E -> error [label="*"]; + Exponent -> error [label="*"]; + +edge [color=red, fontcolor=red]; + + Start -> Start [label="NL/[Newline] "]; + Id -> Start [label="space/ID"]; + Int -> Start [label="space/Int"]; + Decimal -> Start [label="space/Float"]; + Exponent -> Start [label="space/Float"]; + + { rank = same; Decimal E Exponent } +} diff --git a/MVaP/MVaP-v0/MVaP/js/LexerMVaP.png b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.png new file mode 100644 index 0000000000000000000000000000000000000000..684d61819f9ccc90f2aeb0fc440f9ec285d6a14f GIT binary patch literal 73986 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 B3|0UD literal 0 HcmV?d00001 diff --git a/MVaP/MVaP-v0/MVaP/js/MVaP.js b/MVaP/MVaP-v0/MVaP/js/MVaP.js new file mode 100644 index 0000000..6466a56 --- /dev/null +++ b/MVaP/MVaP-v0/MVaP/js/MVaP.js @@ -0,0 +1,374 @@ +// MVàP + +let debugLexer = false; +let debug = true; + +/** token lexicaux */ +const T_ID = 0; +const T_INT = 1; +const T_FLOAT = 2; +const T_SPACE = 3; +const T_NL = 4; +const T_ERROR = 5; +const T_EOF = 6; + +T_Text = [ "T_ID", "T_INT", "T_FLOAT", "T_SPACE", "T_NL", "T_ERROR", "T_EOF" ]; + +/** token grammaticaux */ +const INSTR1 = 0; +const INSTR2 = 1; +const INT = 2; +const INSTR2F = 3; +const FLOAT = 4; +const LABEL = 5; +const JUMP = 6; +const NEWLINE = 7; + +class MVaP { + + codes = [ // pour l'interprète de MVàP + [ "ADD", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2+p1); } ], + [ "SUB", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2-p1); } ], + [ "MUL", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2*p1); } ], + [ "DIV", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(Math.floor(p2/p1)); } ], + [ "INF", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2 { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2<=p1?1:0); } ], + [ "SUP", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2>p1?1:0); } ], + [ "SUPEQ", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2>=p1?1:0); } ], + [ "EQUAL", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2==p1?1:0); } ], + [ "NEQ", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2!=p1?1:0); } ], + [ "FADD", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2+d1); } ], + [ "FSUB", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2-d1); } ], + [ "FMUL", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2*d1); } ], + [ "FDIV", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2/d1); } ], + [ "FINF", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2 { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2<=d1?1:0); } ], + [ "FSUP", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2>d1?1:0); } ], + [ "FSUPEQ", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2>=d1?1:0); } ], + [ "FEQUAL", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2==d1?1:0); } ], + [ "FNEQ", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2!=d1?1:0); } ], + [ "ITOF", INSTR1, () => { let p1 = this.stack.pop(); this.trace("ITOF "+p1); this.stack.pushFloat64(p1); } ], + [ "FTOI", INSTR1, () => { this.stack.push(Math.round(this.stack.popFloat64())); } ], + [ "RETURN", INSTR1, () => { while(this.stack.getSize() > this.fp) this.stack.pop(); + this.fp = this.stack.pop(); this.pc = this.stack.pop(); } ], + [ "POP", INSTR1, () => { this.stack.pop(); } ], + [ "READ", INSTR1, () => { this.stack.push(0); } ], // on lit toujours 0 (idée : prendre le contenu d'un input de type text spécial + [ "WRITE", INSTR1, () => { this.trace(this.stack.peek()+"\n"); } ], + [ "WRITEF", INSTR1, () => { this.trace(this.stack.peekFloat64()+"\n"); } ], + [ "PADD", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2+p1); } ], + [ "PUSHGP", INSTR1, () => { this.stack.push(0); } ], + [ "PUSHFP", INSTR1, () => { this.stack.push(this.fp); } ], + [ "DUP", INSTR1, () => { this.stack.push(this.stack.peek()); } ], + + [ "PUSHI", INSTR2, () => { this.stack.push(this.program.get(this.pc++)); } ], + [ "PUSHG", INSTR2, () => { this.stack.push(this.stack.get(this.program.get(this.pc++)));} ], + [ "STOREG", INSTR2, () => { this.stack.set(this.program.get(this.pc++), this.stack.pop())} ], + [ "PUSHL", INSTR2, () => { this.stack.push(this.stack.get(this.fp+this.program.get(this.pc++))); } ], + [ "STOREL", INSTR2, () => { this.stack.set(this.fp+this.program.get(this.pc++), this.stack.pop()); } ], + [ "PUSHR", INSTR2, () => { this.stack.push(this.stack.get(this.stack.pop()+this.program.get(this.pc++))); } ], + [ "STORER", INSTR2, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.set(p2+this.program.get(this.pc++)); } ], + [ "FREE", INSTR2, () => { this.stack.doPop(this.program.get(this.pc++)); } ], + [ "ALLOC", INSTR2, () => { this.stack.doPush(this.program.get(this.pc++)); } ], + [ "PUSHF", INSTR2F, () => { this.stack.pushFloat64(this.program.getFloat64(this.pc)); this.pc += 2; } ], + [ "CALL", JUMP, () => { this.stack.push(this.pc+1); this.stack.push(this.fp); + this.fp = this.stack.getSize(); + this.pc = this.program.get(this.pc); } ], + [ "JUMP", JUMP, () => { this.pc = this.program.get(this.pc); } ], + [ "JUMPF", JUMP, () => { if (this.stack.pop()==0) this.pc = this.program.get(this.pc); + else this.pc++; } ], + [ "JUMPI", JUMP, () => { this.pc = this.program.get(this.pc)+this.stack.pop();} ], + + [ "HALT", INSTR1, () => { return true; } ], + + [ "LABEL", LABEL, /* erreur interne */ ] + ]; + /*** Ajouter instr : READF WRITEF POPF */ + + tokens = []; // indexe le tableau codes sur son premier élément + + text = ""; + + // + // see LexerMVaP.png for the DFA diagram + state = "Start"; + text; // le texte à analyser + index = 0; // index dans la chaîne text + lineNumber = 1; + + transitions = [ + { state: "Start", next: "Start", test: (c) => { return c == "\n"; }, token: T_NL }, + { state: "Start", next: "Start", test: (c) => { return c.trim() == ""; }, token: false }, + { state: "Start", next: "Id", test: (c) => { return "A" <= c && c <= "Z"; }, token: false }, + { state: "Id", next: "Id", test: (c) => { return "A" <= c && c <= "Z"; }, token: false}, + { state: "Id", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_ID}, + { state: "Start", next: "Int", test: (c) => { return ("0" <= c && c <= "9")||c=="-"||c=="+"; }, token: false }, + { state: "Int", next: "Int", test: (c) => { return "0" <= c && c <= "9"; }, token: false }, + { state: "Int", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_INT }, + { state: "Int", next: "Decimal", test: (c) => { return c == "."; }, token: false }, + { state: "Int", next: "E", test: (c) => { return c == "E"; }, token: false }, + { state: "Decimal", next: "Decimal", test: (c) => { return "0" <= c && c <= "9"; }, token: false }, + { state: "Decimal", next: "E", test: (c) => { return c == "E"; }, token: false }, + { state: "Decimal", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_FLOAT }, + { state: "E", next: "Exponent", test: (c) => { return ("0"<=c && c<="9")||c=="-"||c=="+"; }, token: false }, + { state: "Exponent", next: "Exponent", test: (c) => { return "0" <= c && c <= "9"; }, token: false }, + { state: "Exponent", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_FLOAT } + // else: error + ]; + + initLexer() { + this.index = 0; + this.lineNumber = 1 + console.log("*****************\n* C'est parti *\n*****************"); + } + + // Donne la transition correspondante à l'état courant et au caractère entrant + transition(c) { + for (let v of this.transitions.values()) { + // on aurait pu indexer les transitions sur state au lieu de tout énumérer + if (this.state == v.state && v.test(c)) { + return v; + } + } + return T_ERROR; + } + + yytext = ""; // contient le texte du jeton syntaxique (nommé comme dans lex/yacc) + + + nextToken() { + let c; + let trans; + while (true) { + c = this.text[this.index]; + if (c === undefined) + return T_EOF; + c = c.toUpperCase(); + trans = this.transition(c); + if (trans == T_ERROR) { this.yytext += c; return T_ERROR; } + if (this.state != trans.next && this.state == "Start") this.yytext =""; + + this.state = trans.next; + this.index++; + + if (Number.isInteger(trans.token)) { + break; + } + this.yytext += c; + } + + // séparateur significatif + if (c == "\n") { + if (trans.token != T_NL) { + this.index--; // ne pas manger la fin de ligne non prise en compte + // une autre façon de dire est que l'on n'incrémente pas l'index sur le renvoi de token + // sauf en cas de token constitué de séparateur + } else + this.lineNumber++; // on en profite pour compter la ligne + } + // console.log(" line " + this.lineNumber + " " + trans.token + " '" + yytex + "' i="+i); + return trans.token; + } + // + + // + + /** Grammaire des instructions + instr + : INSTR1 T_NL + | INSTR2 T_INT T_NL + | JUMP T_INT T_NL + | INSTR2F T_FLOAT T_NL + | LABEL T_NL + | T_NL + ; + */ + + program;// Pile contenant le programme compilé + adressesLabels; // adresse des étiquettes pour l'assemblage + + analyse() { + + this.initLexer(); + + let token; // le jeton lexical courant + let state = NEWLINE; // état de l'analyseur grammatical (ici le précédent syntagme grammatical) + this.program = new Pile(); + this.adressesLabels = []; + + while (true) { + this.yytext = ""; + token = this.nextToken(); + if (debugLexer) + console.log("** nextToken line "+this.lineNumber+" token "+token+" "+T_Text[token]+" '" +this.yytext+"' index "+this.index+" state "+state); + + switch(token) { + case T_EOF: + return true; + case T_ID: + let k = this.tokens[this.yytext]; + if (k === undefined || state != NEWLINE) return false; + state = this.codes[k][1]; + if (state != LABEL) { // pas d'instruction LABEL dans le code + this.program.push(k); + } + break; + case T_INT: + if (state == LABEL) { // on mémorise juste l'adresse pour la passe d'assemblage + this.adressesLabels[Number(this.yytext)] = this.program.getSize(); // ± 1 who knows? + } else if(state == INSTR2 || state == JUMP) { + this.program.push(Number(this.yytext)); + } else return false; + state = INT; + break; + case T_FLOAT: + if (state != INSTR2F) return false; + state = FLOAT; + this.program.pushFloat64(Number(this.yytext)); + break; + case T_NL: + if (state == INSTR2 || state == JUMP || state == INSTR2F) return false; + state = NEWLINE; + break; + case T_ERROR: + return false; + default: + alert("Erreur interne prévenir la maintenance d'urgence"); + return false; + } + } + console.log("Programme correct syntaxiquement"); + return true; + } + + assemble() { + // change les numéros d'étiquettes par les adresses des instructions pointées. + console.log("Label "+this.adressesLabels); + console.log(this.dumpProgram()); + + for (let i = 0; i < this.program.getSize(); i++) { + let k = this.program.get(i); + // Attention il faut compter si par malchance un entier = code d'un saut + switch (this.codes[k][1]) { + case INSTR1: + break; + case INSTR2: + i++; // on saute l'entier qui suit + break; + case INSTR2F: + i += 2; // on saute le flottant qui suit + break; + case JUMP: // met à jour l'adresse du saut + i++; + console.log("--- set "+i); + this.program.set(i, this.adressesLabels[this.program.get(i)]); + break; + default: + alert("Erreur assemblage"); + } + } + // console.log(this.dumpProgram()); + } + // + + + dumpInstruction(i, result) { + let code = this.codes[this.program.get(i)]; + result += code[0].padEnd(6, ' '); + switch (code[1]) { + case INSTR2: + case JUMP: + result += this.program.get(++i).toString().padStart(7, ' '); + break; + case INSTR2F: + result += this.program.getFloat64(++i).toString().padStart(7, ' '); + i++; + break; + default: + result += " "; + } + + return [i, result]; + } + + dumpProgram() { + let result = ""; + result += this.program + "\n"; + + result += " Adr | Instruction\n-----+---------------\n"; + for(let i = 0; i < this.program.getSize(); i++) { + result += i.toString().padStart(4, " ")+" | "; + [i, result] = this.dumpInstruction(i, result); + result += "\n"; + } + return result; + } + + constructor() { + // init tokens + for (let k of this.codes.keys()) + this.tokens[this.codes[k][0]] = k; + } + + // charge et compile le code + load(text) { + this.text = text; + // on insère une fin de ligne si le texte n'en a pas à sa fin + if (text[text.length-1] != "\n") this.text = text+"\n"; + if (! this.analyse()) { + alert("Erreur ligne "+this.lineNumber+" sur '" +this.yytext+"'"); + return; + } + this.assemble(); + } + + pc = 0; + fp = 0; + stack; + + runcode(maxSteps, d) { + debug = d; + //for (let i = 0; i < this.codes.length; i++) console.log(i+ " "+ this.codes[i][0]); + this.pc = 0; + this.fp = 0; + this.stack = new Pile(); + + try { + if (debug) + this.trace("Programme\n"+this.dumpProgram() + "\nTraces exécution\n" + + " pc | Instruction | fp pile\n" + + "=====+===============+=============================\n"); + + for (let i= 0; i < maxSteps; i++) // while (true) + { + if (this.pc < 0 || this.pc >= this.program.getSize()) + break; + + if (debug) { + let s = this.pc.toString().padStart(4, " ")+" | "; + let junk; + [junk, s] = this.dumpInstruction(this.pc, s); + s += " |"+this.fp.toString().padStart(4,' ')+' '+this.stack.toString()+"\n"; + this.trace(s); + } + + if (this.codes[this.program.get(this.pc++)][2]() === true) + break; + } + } catch(e) { + this.trace(e); + console.error(e); + } + } + + trace(s) { + traces.innerText += s; + console.log(s); + } + +} + + + + + + diff --git a/MVaP/MVaP-v0/MVaP/js/Pile.js b/MVaP/MVaP-v0/MVaP/js/Pile.js new file mode 100644 index 0000000..f78f210 --- /dev/null +++ b/MVaP/MVaP-v0/MVaP/js/Pile.js @@ -0,0 +1,153 @@ +// Class Pile +// Auteur : Jacques Madelaine + +// Une Pile est essentiellement une pile d'entiers ("int32") +// Elle peut aussi empiler et dépiler des flottants définis sur 64 bits. +// L'index est sur les entiers. + +// Rappel : en JavaScript les Number sont tous stockés comme des flottants 64 bits. +// Il faut donc voir cette Pile comme un objet pédagogique +// et non une implémentation optimale en JavaScipt. + +"use strict"; + +class Pile { + buffer; // ArrayBuffer de bytes + pile; // On va utiliser 4 bytes pour les entiers et 8 pour les flottants + haut = 0; // index de sommet de pile en bytes + + // size : taille en bytes de la pile + constructor(size) { + if (size === undefined) + size = 1000; + + this.buffer = new ArrayBuffer(size); + this.pile = new DataView(this.buffer); + } + + push(i) { + if (! Number.isInteger(i)) + throw new TypeError("Try to push a non integer"); + this.pile.setInt32(this.haut, i); + this.haut += 4; + } + + doPush(nb) { for(; nb > 0; nb--) this.push(0); } + + pop() { + this.haut -= 4; + return this.pile.getInt32(this.haut); + } + + doPop(nb) { for(; nb > 0; nb--) this.pop(); } + + peek() { + return this.pile.getInt32(this.haut-4); + } + + set(index, i) { + if (! Number.isInteger(i)) + throw new TypeError("Try to set a non integer"); + this.pile.setInt32(index*4, i); + } + + get(index) { + return this.pile.getInt32(index*4); + } + + + pushFloat64(f) { + this.pile.setFloat64(this.haut, f); + this.haut += 8; + } + + popFloat64() { + this.haut -= 8; + return this.pile.getFloat64(this.haut); + } + + peekFloat64() { + return this.pile.getFloat64(this.haut-8); + } + + setFloat64(index, f) { + this.pile.setFloat64(index*4, f); + } + + getFloat64(index) { + return this.pile.getFloat64(index*4); + } + + getMaxSize() { + return this.buffer.byteLength/2; + } + + getSize() { + return this.haut/4; + } + + toString() { + let out = "[ "; + for (let i = 0; i < this.getSize(); i++) + out += this.get(i) + ", "; + return out + " ] " + this.getSize(); + } + +} + + +/* + +let p = new Pile(); +try { + let d = 12.34; + let i = 0x7FFFFFFF; + let j = 0; + p.push(i); + j = p.peek(); + console.log(i + " =?= " + j); + + let N = 5; + for(let n = 0; n < N; n++) { + p.push(n); + console.log("push "+n+" " + n); + } + + console.log("get(2) " + p.get(2)); + console.log(p.toString()); + + for(let n = N; n > 0; n--) { + let m = p.pop(); + // if (2*n != m) + console.log("push "+ n + " pop " + m); + } + p.pop(); + + p.push(40); + p.pushFloat64(d); + p.pushFloat64(13.34); + p.push(i); + console.log(p.toString()); + + for (let n = 0; n<6;n++) + console.log("p.getFloat64("+n+") = "+p.getFloat64(n)); + + p.pop(); + p.popFloat64(); + let e = p.popFloat64(); + console.log(d + " =?= " + e); + + + d = -1; + p.pushFloat64(d); + e = p.popFloat64(); + console.log(d + " =?= " + e); + // + // for (i = 0 ; i < 1000000; i++) + // p.push(i); +} catch(e) { + console.error(e); +} +*/ + +