MVaP en javascript
This commit is contained in:
parent
460b23f88e
commit
9d2a57e7bd
72
MVaP/MVaP-v0/MVaP/index.html
Normal file
72
MVaP/MVaP-v0/MVaP/index.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<title>MVàP</title>
|
||||||
|
|
||||||
|
<script src="js/Pile.js" type="text/javascript"></script>
|
||||||
|
<script src="js/MVaP.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
body{ color: #333; font: 13px 'Lucida Grande', Verdana, sans-serif; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Machine Virtuelle à Pile</h1>
|
||||||
|
|
||||||
|
<h2>Historique</h2>
|
||||||
|
Blabla sur la MVàP...
|
||||||
|
|
||||||
|
<h2>Documentation</h2>
|
||||||
|
Toute la doc
|
||||||
|
<p>
|
||||||
|
lorem ipsum
|
||||||
|
<h2>La MVàP</h2>
|
||||||
|
<h3>Entrez le code</h3>
|
||||||
|
<div class="runcode">
|
||||||
|
<textarea id="codeMVaP" name="Code MVàP" label="Enter your code" rows="15" cols="33" spellcheck="false">
|
||||||
|
PUSHI 2
|
||||||
|
DUP
|
||||||
|
PUSHI 3
|
||||||
|
ADD
|
||||||
|
PUSHI 4
|
||||||
|
MUL
|
||||||
|
WRITE
|
||||||
|
HALT
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Exécution</h3>
|
||||||
|
<script>
|
||||||
|
var M = "";
|
||||||
|
function runcode() {
|
||||||
|
let text = document.getElementById("codeMVaP").value;
|
||||||
|
let d = document.getElementById("debug").checked;
|
||||||
|
let maxSteps = document.getElementById("MaxSteps").value;
|
||||||
|
if (M == "") M = new MVaP();
|
||||||
|
M.load(text);
|
||||||
|
M.runcode(maxSteps, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<input type="button" value="Run" onclick="runcode();"/>
|
||||||
|
<label for="MaxSteps">Nombre maximum de pas (O pour pas de limite)</label>
|
||||||
|
<input type="text" id="MaxSteps" name="MaxSteps" value="1000" minLength="4" maxLength="8" size="10"/>
|
||||||
|
<label for="debug">Traces pas à pas</label>
|
||||||
|
<input type="checkbox" id="debug" name="debug" checked />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<input type="button" value="Nettoyer les traces" onclick="traces.innerText='';"/>
|
||||||
|
<div id="traces"></div>
|
||||||
|
</pre>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
216
MVaP/MVaP-v0/MVaP/js/CBaP.js
Normal file
216
MVaP/MVaP-v0/MVaP/js/CBaP.js
Normal file
@ -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); }
|
||||||
|
}
|
33
MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot
Normal file
33
MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot
Normal file
@ -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 }
|
||||||
|
}
|
BIN
MVaP/MVaP-v0/MVaP/js/LexerMVaP.png
Normal file
BIN
MVaP/MVaP-v0/MVaP/js/LexerMVaP.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
374
MVaP/MVaP-v0/MVaP/js/MVaP.js
Normal file
374
MVaP/MVaP-v0/MVaP/js/MVaP.js
Normal file
@ -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<p1?1:0); } ],
|
||||||
|
[ "INFEQ", INSTR1, () => { 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<d1?1:0); } ],
|
||||||
|
[ "FINFEQ", INSTR1, () => { 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 = "";
|
||||||
|
|
||||||
|
// <Lexer>
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
// </Lexer>
|
||||||
|
|
||||||
|
// <Analyse sémantique et assemblage>
|
||||||
|
|
||||||
|
/** 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());
|
||||||
|
}
|
||||||
|
// </Analyse sémantique et assemblage>
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
153
MVaP/MVaP-v0/MVaP/js/Pile.js
Normal file
153
MVaP/MVaP-v0/MVaP/js/Pile.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user