added things

This commit is contained in:
2025-02-05 20:22:57 +00:00
committed by GitHub
parent 48024e5b02
commit 42be1f12ac
38 changed files with 12526 additions and 0 deletions
@@ -0,0 +1,968 @@
var Compiler, LocalLayer;
Compiler = (function() {
class Compiler {
constructor(program) {
var i, j, len, ref, s;
this.program = program;
this.code_saves = [];
this.code = "";
this.code = [this.code];
this.routine = new Routine();
this.locals = new Locals(this);
this.count = 0;
ref = this.program.statements;
for (i = j = 0, len = ref.length; j < len; i = ++j) {
s = ref[i];
this.compile(s);
if (i < this.program.statements.length - 1) {
this.routine.POP(s);
}
}
this.routine.optimize();
this.routine.resolveLabels();
this.count += this.routine.opcodes.length;
this.routine.locals_size = this.locals.max_index;
}
// console.info(JSON.stringify @routine.export())
// @routine = new Routine(0).import( @routine.export() )
compile(statement) {
if (statement instanceof Program.Value) {
return this.compileValue(statement);
} else if (statement instanceof Program.Operation) {
return this.compileOperation(statement);
} else if (statement instanceof Program.Assignment) {
return this.compileAssignment(statement);
} else if (statement instanceof Program.Variable) {
return this.compileVariable(statement);
} else if (statement instanceof Program.Function) {
return this.compileFunction(statement);
} else if (statement instanceof Program.FunctionCall) {
return this.compileFunctionCall(statement);
} else if (statement instanceof Program.While) {
return this.compileWhile(statement);
}
if (statement instanceof Program.SelfAssignment) {
return this.compileSelfAssignment(statement);
} else if (statement instanceof Program.Braced) {
return this.compileBraced(statement);
} else if (statement instanceof Program.CreateObject) {
return this.compileCreateObject(statement);
} else if (statement instanceof Program.Field) {
return this.compileField(statement);
} else if (statement instanceof Program.Negate) {
return this.compileNegate(statement);
} else if (statement instanceof Program.For) {
return this.compileFor(statement);
} else if (statement instanceof Program.ForIn) {
return this.compileForIn(statement);
} else if (statement instanceof Program.Not) {
return this.compileNot(statement);
} else if (statement instanceof Program.Return) {
return this.compileReturn(statement);
} else if (statement instanceof Program.Condition) {
return this.compileCondition(statement);
} else if (statement instanceof Program.Break) {
return this.compileBreak(statement);
} else if (statement instanceof Program.Continue) {
return this.compileContinue(statement);
} else if (statement instanceof Program.CreateClass) {
return this.compileCreateClass(statement);
} else if (statement instanceof Program.NewCall) {
return this.compileNewCall(statement);
} else if (statement instanceof Program.After) {
return this.compileAfter(statement);
} else if (statement instanceof Program.Every) {
return this.compileEvery(statement);
} else if (statement instanceof Program.Do) {
return this.compileDo(statement);
} else if (statement instanceof Program.Sleep) {
return this.compileSleep(statement);
} else if (statement instanceof Program.Delete) {
return this.compileDelete(statement);
} else if (true) {
console.info(statement);
throw "Not implemented";
}
}
compileAssignment(statement) {
var arg_index, f, i, index, j, ref;
if (statement.local) {
if (statement.field instanceof Program.Variable) {
if (statement.expression instanceof Program.Function) {
index = this.locals.register(statement.field.identifier); //# register function locally first
this.compile(statement.expression); //# then compile function which may refer to itself
this.routine.arg1[this.routine.arg1.length - 1].import_self = index;
return this.routine.STORE_LOCAL(index, statement);
} else if (statement.expression instanceof Program.After || statement.expression instanceof Program.Do || statement.expression instanceof Program.Every) {
index = this.locals.register(statement.field.identifier); //# register thread locally first
arg_index = this.routine.arg1.length; //# thread main routine will land here
this.compile(statement.expression); //# then compile function which may refer to itself
this.routine.arg1[arg_index].import_self = index;
return this.routine.STORE_LOCAL(index, statement);
} else {
this.compile(statement.expression); //# first compile expression which may refer to another local with same name
index = this.locals.register(statement.field.identifier); //# then register a local for that name
return this.routine.STORE_LOCAL(index, statement);
}
} else {
throw "illegal";
}
} else {
if (statement.field instanceof Program.Variable) {
if (this.locals.get(statement.field.identifier) != null) {
this.compile(statement.expression);
index = this.locals.get(statement.field.identifier);
this.routine.STORE_LOCAL(index, statement);
} else if (statement.expression instanceof Program.CreateClass) {
return this.compileUpdateClass(statement.expression, statement.field.identifier);
} else {
this.compile(statement.expression);
this.routine.STORE_VARIABLE(statement.field.identifier, statement);
}
} else {
f = statement.field;
if (f.expression instanceof Program.Variable) {
if (f.expression.identifier === "this") {
this.routine.LOAD_THIS(f);
} else if (this.locals.get(f.expression.identifier) != null) {
index = this.locals.get(f.expression.identifier);
this.routine.LOAD_LOCAL_OBJECT(index, f.expression);
} else if (f.expression.identifier === "global") {
this.routine.LOAD_GLOBAL(f);
} else {
this.routine.LOAD_VARIABLE_OBJECT(f.expression.identifier, statement);
}
} else {
this.compile(f.expression);
this.routine.MAKE_OBJECT(statement);
}
for (i = j = 0, ref = f.chain.length - 2; j <= ref; i = j += 1) {
this.compile(f.chain[i]);
this.routine.LOAD_PROPERTY_OBJECT(f.chain[i]);
}
this.compile(f.chain[f.chain.length - 1]);
this.compile(statement.expression);
return this.routine.STORE_PROPERTY(statement);
}
}
}
compileSelfAssignment(statement) {
var c, f, i, index, j, op, ref;
switch (statement.operation) {
case Token.TYPE_PLUS_EQUALS:
op = "ADD";
break;
case Token.TYPE_MINUS_EQUALS:
op = "SUB";
break;
case Token.TYPE_MULTIPLY_EQUALS:
op = "MUL";
break;
case Token.TYPE_DIVIDE_EQUALS:
op = "DIV";
break;
case Token.TYPE_MODULO_EQUALS:
op = "MODULO";
break;
case Token.TYPE_AND_EQUALS:
op = "BINARY_AND";
break;
case Token.TYPE_OR_EQUALS:
op = "BINARY_OR";
}
if (statement.field instanceof Program.Variable) {
if (this.locals.get(statement.field.identifier) != null) {
index = this.locals.get(statement.field.identifier);
this.routine.LOAD_LOCAL(index, statement);
this.compile(statement.expression);
this.routine[op](statement, 1);
this.routine.STORE_LOCAL(index, statement);
} else {
this.routine.LOAD_VARIABLE(statement.field.identifier, statement);
this.compile(statement.expression);
this.routine[op](statement, 1);
this.routine.STORE_VARIABLE(statement.field.identifier, statement);
}
} else {
f = statement.field;
if (f.expression instanceof Program.Variable) {
if (f.expression.identifier === "this") {
this.routine.LOAD_THIS(f);
} else if (this.locals.get(f.expression.identifier) != null) {
index = this.locals.get(f.expression.identifier);
this.routine.LOAD_LOCAL_OBJECT(index, statement);
} else if (f.expression.identifier === "global") {
this.routine.LOAD_GLOBAL(f);
} else {
this.routine.LOAD_VARIABLE_OBJECT(f.expression.identifier, statement);
}
} else {
this.compile(f.expression);
this.routine.MAKE_OBJECT(statement);
}
for (i = j = 0, ref = f.chain.length - 2; j <= ref; i = j += 1) {
this.compile(f.chain[i]);
this.routine.LOAD_PROPERTY_OBJECT(f.chain[i]);
}
c = f.chain[f.chain.length - 1];
this.compile(f.chain[f.chain.length - 1]);
this.routine.LOAD_PROPERTY_ATOP(statement);
this.compile(statement.expression);
this.routine[op](statement, 1);
return this.routine.STORE_PROPERTY(statement);
}
}
compileOperation(op) {
var jump, ref, ref1;
if ((ref = op.operation) === "+" || ref === "-" || ref === "*" || ref === "/" || ref === "%" || ref === "&" || ref === "|" || ref === "<<" || ref === ">>") {
this.compile(op.term1);
this.compile(op.term2);
switch (op.operation) {
case "+":
this.routine.ADD(op);
break;
case "-":
this.routine.SUB(op);
break;
case "*":
this.routine.MUL(op);
break;
case "/":
this.routine.DIV(op);
break;
case "%":
this.routine.MODULO(op);
break;
case "&":
this.routine.BINARY_AND(op);
break;
case "|":
this.routine.BINARY_OR(op);
break;
case "<<":
this.routine.SHIFT_LEFT(op);
break;
case ">>":
this.routine.SHIFT_RIGHT(op);
}
} else if ((ref1 = op.operation) === "==" || ref1 === "!=" || ref1 === "<" || ref1 === ">" || ref1 === "<=" || ref1 === ">=") {
this.compile(op.term1);
this.compile(op.term2);
switch (op.operation) {
case "==":
this.routine.EQ(op);
break;
case "!=":
this.routine.NEQ(op);
break;
case "<":
this.routine.LT(op);
break;
case ">":
this.routine.GT(op);
break;
case "<=":
this.routine.LTE(op);
break;
case ">=":
this.routine.GTE(op);
}
} else if (op.operation === "and") {
jump = this.routine.createLabel("and");
op.term1.nowarning = true;
op.term2.nowarning = true;
this.compile(op.term1);
this.routine.JUMPN_NOPOP(jump, op);
this.routine.POP(op);
this.compile(op.term2);
return this.routine.setLabel(jump);
} else if (op.operation === "or") {
jump = this.routine.createLabel("or");
op.term1.nowarning = true;
op.term2.nowarning = true;
this.compile(op.term1);
this.routine.JUMPY_NOPOP(jump, op);
this.routine.POP(op);
this.compile(op.term2);
return this.routine.setLabel(jump);
} else if (op.operation === "^") {
this.compile(op.term1);
this.compile(op.term2);
return this.routine.BINARY_OP(Compiler.predefined_binary_functions.pow, op);
} else {
return "";
}
}
compileBraced(expression) {
this.compile(expression.expression);
}
compileNegate(expression) {
if (expression.expression instanceof Program.Value && expression.expression.type === Program.Value.TYPE_NUMBER) {
return this.routine.LOAD_VALUE(-expression.expression.value, expression);
} else {
this.compile(expression.expression);
return this.routine.NEGATE(expression);
}
}
compileNot(expression) {
expression.expression.nowarning = true;
this.compile(expression.expression);
return this.routine.NOT(expression);
}
compileValue(value) {
var i, j, ref;
switch (value.type) {
case Program.Value.TYPE_NUMBER:
this.routine.LOAD_VALUE(value.value, value);
break;
case Program.Value.TYPE_STRING:
this.routine.LOAD_VALUE(value.value, value);
break;
case Program.Value.TYPE_ARRAY:
this.routine.CREATE_ARRAY(value);
for (i = j = 0, ref = value.value.length - 1; j <= ref; i = j += 1) {
this.routine.LOAD_VALUE(i, value);
this.compile(value.value[i]);
this.routine.CREATE_PROPERTY(value);
}
}
}
compileVariable(variable) {
var index, v;
v = variable.identifier;
if (v === "this") {
return this.routine.LOAD_THIS(variable);
} else if (v === "global") {
return this.routine.LOAD_GLOBAL(variable);
} else if (Compiler.predefined_values[v] != null) {
return this.routine.LOAD_VALUE(Compiler.predefined_values[v], variable);
} else if (this.locals.get(v) != null) {
index = this.locals.get(v);
return this.routine.LOAD_LOCAL(index, variable);
} else {
return this.routine.LOAD_VARIABLE(v, variable);
}
}
compileField(field) {
var c, i, id, index, j, k, len, ref, ref1;
if (field.expression.identifier === "keyboard" || field.expression.identifier === "gamepad") {
field.nowarning = true;
}
c = field.chain[field.chain.length - 1];
if (c instanceof Program.Value && c.value === "type") {
if (field.chain.length === 1) {
if (field.expression instanceof Program.Variable) { // variable.type
id = field.expression.identifier;
if (this.locals.get(id) != null) {
index = this.locals.get(id);
this.routine.LOAD_LOCAL(index, field);
this.routine.TYPE(field);
} else if (Compiler.predefined_values[id] != null) {
this.routine.LOAD_VALUE("number", field);
} else if ((Compiler.predefined_unary_functions[id] != null) || Compiler.predefined_binary_functions[id]) {
this.routine.LOAD_VALUE("function", field);
} else {
this.routine.VARIABLE_TYPE(id, field.expression);
}
} else {
this.compile(field.expression);
this.routine.TYPE(field);
}
} else {
this.compile(field.expression);
for (i = j = 0, ref = field.chain.length - 3; j <= ref; i = j += 1) {
this.compile(field.chain[i]);
this.routine.LOAD_PROPERTY(field);
}
this.compile(field.chain[field.chain.length - 2]);
this.routine.PROPERTY_TYPE(field.expression);
}
} else {
this.compile(field.expression);
ref1 = field.chain;
for (k = 0, len = ref1.length; k < len; k++) {
c = ref1[k];
this.compile(c);
this.routine.LOAD_PROPERTY(field);
}
}
}
compileFieldParent(field) {
var c, i, j, ref;
this.compile(field.expression);
for (i = j = 0, ref = field.chain.length - 2; j <= ref; i = j += 1) {
c = field.chain[i];
this.compile(c);
this.routine.LOAD_PROPERTY(field);
}
}
compileFunctionCall(call) {
var a, funk, i, index, j, k, l, len, len1, len2, len3, len4, m, n, ref, ref1, ref2, ref3, ref4;
if (call.expression instanceof Program.Field) {
ref = call.args;
for (i = j = 0, len = ref.length; j < len; i = ++j) {
a = ref[i];
this.compile(a);
}
this.compileFieldParent(call.expression);
this.compile(call.expression.chain[call.expression.chain.length - 1]);
return this.routine.FUNCTION_APPLY_PROPERTY(call.args.length, call);
} else if (call.expression instanceof Program.Variable) {
if (Compiler.predefined_unary_functions[call.expression.identifier] != null) {
funk = Compiler.predefined_unary_functions[call.expression.identifier];
if (call.args.length > 0) {
this.compile(call.args[0]);
} else {
this.routine.LOAD_VALUE(0, call);
}
return this.routine.UNARY_OP(funk, call);
} else if (Compiler.predefined_binary_functions[call.expression.identifier] != null) {
funk = Compiler.predefined_binary_functions[call.expression.identifier];
if (call.args.length > 0) {
this.compile(call.args[0]);
} else {
this.routine.LOAD_VALUE(0, call);
}
if (call.args.length > 1) {
this.compile(call.args[1]);
} else {
this.routine.LOAD_VALUE(0, call);
}
return this.routine.BINARY_OP(funk, call);
} else if (call.expression.identifier === "super") {
ref1 = call.args;
for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) {
a = ref1[i];
this.compile(a);
}
return this.routine.SUPER_CALL(call.args.length, call);
} else if (this.locals.get(call.expression.identifier) != null) {
ref2 = call.args;
for (i = l = 0, len2 = ref2.length; l < len2; i = ++l) {
a = ref2[i];
this.compile(a);
}
index = this.locals.get(call.expression.identifier);
this.routine.LOAD_LOCAL(index, call);
return this.routine.FUNCTION_CALL(call.args.length, call);
} else {
ref3 = call.args;
for (i = m = 0, len3 = ref3.length; m < len3; i = ++m) {
a = ref3[i];
this.compile(a);
}
this.routine.LOAD_VALUE(call.expression.identifier, call);
return this.routine.FUNCTION_APPLY_VARIABLE(call.args.length, call);
}
} else {
ref4 = call.args;
for (n = 0, len4 = ref4.length; n < len4; n++) {
a = ref4[n];
this.compile(a);
}
this.compile(call.expression);
return this.routine.FUNCTION_CALL(call.args.length, call);
}
}
compileFor(forloop) {
var for_continue, for_end, for_start, iterator, save_break, save_continue;
iterator = this.locals.register(forloop.iterator);
this.locals.allocate(); // range_to
this.locals.allocate(); // step
this.compile(forloop.range_from);
this.routine.STORE_LOCAL(iterator, forloop);
this.routine.POP(forloop);
this.compile(forloop.range_to);
if (forloop.range_by !== 0) {
this.compile(forloop.range_by);
} else {
this.routine.LOAD_VALUE(0, forloop);
}
for_start = this.routine.createLabel("for_start");
for_continue = this.routine.createLabel("for_continue");
for_end = this.routine.createLabel("for_end");
this.routine.FORLOOP_INIT([iterator, for_end], forloop);
this.routine.setLabel(for_start);
this.locals.push();
save_break = this.break_label;
save_continue = this.continue_label;
this.break_label = for_end;
this.continue_label = for_continue;
this.compileSequence(forloop.sequence);
this.break_label = save_break;
this.continue_label = save_continue;
this.routine.setLabel(for_continue);
this.routine.FORLOOP_CONTROL([iterator, for_start], forloop);
this.routine.setLabel(for_end);
return this.locals.pop();
}
compileForIn(forloop) {
var for_continue, for_end, for_start, iterator, save_break, save_continue;
iterator = this.locals.register(forloop.iterator);
this.locals.allocate(); // array
this.locals.allocate(); // index
this.compile(forloop.list);
for_start = this.routine.createLabel("for_start");
for_continue = this.routine.createLabel("for_continue");
for_end = this.routine.createLabel("for_end");
this.routine.FORIN_INIT([iterator, for_end], forloop);
this.routine.setLabel(for_start);
this.locals.push();
save_break = this.break_label;
save_continue = this.continue_label;
this.break_label = for_end;
this.continue_label = for_continue;
this.compileSequence(forloop.sequence);
this.break_label = save_break;
this.continue_label = save_continue;
this.routine.setLabel(for_continue);
this.routine.FORIN_CONTROL([iterator, for_start], forloop);
this.routine.setLabel(for_end);
return this.locals.pop();
}
compileSequence(sequence) {
var i, j, ref;
for (i = j = 0, ref = sequence.length - 1; j <= ref; i = j += 1) {
if (!sequence[i].nopop) {
this.routine.POP(sequence[i]);
}
this.compile(sequence[i]);
}
}
compileWhile(whiloop) {
var end, save_break, save_continue, start;
this.locals.push();
start = this.routine.createLabel("while_start");
end = this.routine.createLabel("while_end");
this.routine.LOAD_VALUE(0, whiloop);
this.routine.setLabel(start);
this.compile(whiloop.condition);
this.routine.JUMPN(end);
save_break = this.break_label;
save_continue = this.continue_label;
this.break_label = end;
this.continue_label = start;
this.compileSequence(whiloop.sequence);
this.routine.JUMP(start, whiloop);
this.break_label = save_break;
this.continue_label = save_continue;
this.routine.setLabel(end);
return this.locals.pop();
}
compileBreak(statement) {
if (this.break_label != null) {
return this.routine.JUMP(this.break_label);
}
}
compileContinue(statement) {
if (this.continue_label != null) {
return this.routine.JUMP(this.continue_label);
}
}
compileFunction(func) {
var r;
r = this.compileFunctionBody(func);
return this.routine.LOAD_ROUTINE(r, func);
}
compileFunctionBody(func) {
var a, args, i, index, j, k, l, label, len, local_index, locals, m, numargs, r, ref, ref1, ref2, ref3, routine;
routine = this.routine;
locals = this.locals;
this.routine = new Routine(func.args != null ? func.args.length : 0);
this.locals = new Locals(this, locals);
local_index = this.locals.index;
this.routine.uses_arguments = true;
if (func.args != null) {
if (this.routine.uses_arguments) {
args = this.locals.register("arguments");
this.routine.STORE_LOCAL(args, func);
this.routine.POP(func);
}
numargs = this.locals.register("+numargs");
this.routine.STORE_LOCAL(numargs, func);
this.routine.POP(func);
for (i = j = ref = func.args.length - 1; j >= 0; i = j += -1) {
a = func.args[i];
index = this.locals.register(a.name);
this.routine.STORE_LOCAL(index, func);
this.routine.POP(func);
}
for (i = k = 0, ref1 = func.args.length - 1; k <= ref1; i = k += 1) {
a = func.args[i];
if (a.default != null) {
index = this.locals.get(a.name);
label = this.routine.createLabel("default_arg");
this.routine.LOAD_VALUE(i, func);
this.routine.LOAD_LOCAL(numargs, func);
this.routine.LT(func);
this.routine.JUMPY(label, func);
this.compile(a.default);
this.routine.STORE_LOCAL(index, func);
this.routine.POP(func);
this.routine.setLabel(label);
}
}
}
if (func.sequence.length > 0) {
for (i = l = 0, ref2 = func.sequence.length - 1; l <= ref2; i = l += 1) {
this.compile(func.sequence[i]);
if (i < func.sequence.length - 1) {
this.routine.POP(func.sequence[i]);
} else {
this.routine.RETURN(func.sequence[i]);
}
}
} else {
this.routine.LOAD_VALUE(0, func);
this.routine.RETURN(func);
}
if ((func.args != null) && !this.locals.arguments_used) {
this.routine.uses_arguments = false;
this.routine.remove(0);
this.routine.remove(0);
}
index = 0;
ref3 = this.locals.imports;
for (m = 0, len = ref3.length; m < len; m++) {
i = ref3[m];
this.routine.OP_INSERT(OPCODES.LOAD_IMPORT, func, index, index * 3);
this.routine.OP_INSERT(OPCODES.STORE_LOCAL, func, i.index, index * 3 + 1);
this.routine.OP_INSERT(OPCODES.POP, func, 0, index * 3 + 2);
this.routine.import_refs.push(i.source);
index += 1;
}
this.routine.optimize();
this.routine.resolveLabels();
this.count += this.routine.opcodes.length;
r = this.routine;
// console.info r.toString()
this.routine.locals_size = this.locals.max_index;
this.routine = routine;
this.locals = locals;
return r;
}
compileReturn(ret) {
if (ret.expression != null) {
this.compile(ret.expression);
return this.routine.RETURN(ret);
} else {
this.routine.LOAD_VALUE(0, ret);
return this.routine.RETURN(ret);
}
}
compileCondition(condition) {
var c, chain, condition_end, condition_next, i, j, ref;
chain = condition.chain;
this.routine.LOAD_VALUE(0, condition);
condition_end = this.routine.createLabel("condition_end");
for (i = j = 0, ref = chain.length - 1; j <= ref; i = j += 1) {
condition_next = this.routine.createLabel("condition_next");
c = chain[i];
c.condition.nowarning = true;
this.compile(c.condition);
this.routine.JUMPN(condition_next);
this.locals.push();
this.compileSequence(c.sequence);
this.locals.pop();
this.routine.JUMP(condition_end, condition);
this.routine.setLabel(condition_next);
if (i === chain.length - 1 && (c.else != null)) {
this.locals.push();
this.compileSequence(c.else);
this.locals.pop();
}
}
this.routine.setLabel(condition_end);
}
formatField(field) {
if (field === "constructor") {
field = "_constructor";
}
return field.toString().replace(/"/g, "\\\"");
}
compileCreateObject(statement) {
var f, j, len, ref;
this.routine.CREATE_OBJECT(statement);
ref = statement.fields;
for (j = 0, len = ref.length; j < len; j++) {
f = ref[j];
this.routine.LOAD_VALUE(f.field, statement);
this.compile(f.value);
this.routine.CREATE_PROPERTY(statement);
}
}
compileCreateClass(statement) {
var f, j, len, ref, variable;
if (statement.ext != null) {
statement.ext.nowarning = true;
this.compile(statement.ext);
} else {
this.routine.LOAD_VALUE(0, statement);
}
variable = (statement.ext != null) && statement.ext instanceof Program.Variable ? statement.ext.identifier : 0;
this.routine.CREATE_CLASS(variable, statement);
ref = statement.fields;
for (j = 0, len = ref.length; j < len; j++) {
f = ref[j];
this.routine.LOAD_VALUE(f.field, statement);
this.compile(f.value);
this.routine.CREATE_PROPERTY(statement);
}
}
compileUpdateClass(statement, variable) {
this.compileCreateClass(statement);
return this.routine.UPDATE_CLASS(variable, statement);
}
compileNewCall(statement) {
var a, call, i, j, len, ref;
call = statement.expression;
this.routine.LOAD_VALUE(0, statement); // reserve spot on stack for the class instance
ref = call.args;
for (i = j = 0, len = ref.length; j < len; i = ++j) {
a = ref[i];
this.compile(a);
}
this.compile(call.expression);
this.routine.NEW_CALL(call.args.length, statement);
return this.routine.POP(statement); // pop return value of class constructor
}
compileAfter(after) {
var r;
r = this.compileFunctionBody(after);
this.routine.LOAD_ROUTINE(r, after);
this.compile(after.delay);
if ((after.multiplier != null) && after.multiplier !== 1) {
this.routine.LOAD_VALUE(after.multiplier, after);
this.routine.MUL(after);
}
return this.routine.AFTER(after);
}
compileEvery(every) {
var r;
r = this.compileFunctionBody(every);
this.routine.LOAD_ROUTINE(r, every);
this.compile(every.delay);
if ((every.multiplier != null) && every.multiplier !== 1) {
this.routine.LOAD_VALUE(every.multiplier, every);
this.routine.MUL(every);
}
return this.routine.EVERY(every);
}
compileDo(dostuff) {
var r;
r = this.compileFunctionBody(dostuff);
this.routine.LOAD_ROUTINE(r, dostuff);
return this.routine.DO(dostuff);
}
compileSleep(sleep) {
this.compile(sleep.delay);
if ((sleep.multiplier != null) && sleep.multiplier !== 1) {
this.routine.LOAD_VALUE(sleep.multiplier, sleep);
this.routine.MUL(sleep);
}
return this.routine.SLEEP(sleep);
}
compileDelete(del) {
var chain, i, j, ref;
if (del.field instanceof Program.Variable) {
this.routine.LOAD_THIS(del);
this.routine.LOAD_VALUE(del.field.identifier, del);
this.routine.DELETE(del);
} else {
this.compile(del.field.expression);
chain = del.field.chain;
for (i = j = 0, ref = chain.length - 1; j <= ref; i = j += 1) {
this.compile(chain[i]);
if (i < chain.length - 1) {
this.routine.LOAD_PROPERTY(del);
}
}
this.routine.DELETE(del);
}
}
exec(context) {
this.processor = new Processor();
this.processor.load(this.routine);
return this.processor.run(context);
}
};
Compiler.predefined_unary_functions = {
"round": Math.round,
"floor": Math.floor,
"ceil": Math.ceil,
"abs": Math.abs,
"sqrt": Math.sqrt,
"sin": Math.sin,
"cos": Math.cos,
"tan": Math.tan,
"acos": Math.acos,
"asin": Math.asin,
"atan": Math.atan,
"sind": function(x) {
return Math.sin(x * Math.PI / 180);
},
"cosd": function(x) {
return Math.cos(x * Math.PI / 180);
},
"tand": function(x) {
return Math.tan(x * Math.PI / 180);
},
"asind": function(x) {
return Math.asin(x) / Math.PI * 180;
},
"acosd": function(x) {
return Math.acos(x) / Math.PI * 180;
},
"atand": function(x) {
return Math.atan(x) / Math.PI * 180;
},
"log": Math.log,
"exp": Math.exp
};
Compiler.predefined_binary_functions = {
"min": Math.min,
"max": Math.max,
"pow": Math.pow,
"atan2": Math.atan2,
"atan2d": function(y, x) {
return Math.atan2(y, x) / Math.PI * 180;
}
};
Compiler.predefined_values = {
PI: Math.PI,
true: 1,
false: 0
};
return Compiler;
}).call(this);
this.Locals = class Locals {
constructor(compiler, parent = null) {
this.compiler = compiler;
this.parent = parent;
this.layers = [];
this.index = 0;
this.max_index = 0;
this.push();
this.imports = [];
}
increment() {
var spot;
spot = this.index++;
this.max_index = Math.max(this.index, this.max_index);
return spot;
}
push() {
return this.layers.push(new LocalLayer(this));
}
pop() {
// resetting the @index below was causing erasure of outer locals
// when used after the block ; such reset is not needed
//@index = @layers[@layers.length-1].start_index
return this.layers.splice(this.layers.length - 1, 1);
}
register(name) {
return this.layers[this.layers.length - 1].register(name);
}
allocate() {
return this.layers[this.layers.length - 1].allocate();
}
get(name) {
var i, index, j, ref, v;
if (name === "arguments") {
this.arguments_used = true;
}
for (i = j = ref = this.layers.length - 1; j >= 0; i = j += -1) {
v = this.layers[i].get(name);
if (v != null) {
return v;
}
}
if (this.parent != null) {
v = this.parent.get(name);
if (v != null) {
index = this.register(name);
this.imports.push({
name: name,
index: index,
source: v
});
return index;
}
}
return null;
}
};
LocalLayer = class LocalLayer {
constructor(locals1) {
this.locals = locals1;
this.start_index = this.locals.index;
this.registered = {};
}
register(name) {
return this.registered[name] = this.locals.increment();
}
allocate() {
return this.locals.increment();
}
get(name) {
if (this.registered[name] != null) {
return this.registered[name];
} else {
return null;
}
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

@@ -0,0 +1,467 @@
<!DOCTYPE html><html><head><title>micro Box</title><meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui=1"><meta charset="UTF-8"><meta name="mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="description" content=""><link rel="manifest" href="manifest.json"><link rel="icon" type="image/png" href="icon64.png"><link rel="apple-touch-icon" sizes="180x180" href="icon180.png"><link rel="icon" type="image/png" sizes="32x32" href="icon32.png"><link rel="icon" type="image/png" sizes="16x16" href="icon16.png"><style>html,body {
margin: 0;
padding: 0;
background-color: #000;
overflow:hidden;
font-family: Verdana;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#canvaswrapper {
text-align: center ;
}
</style><style>@font-face { font-family: "BitCell" ; src: url("fonts/BitCell.ttf") format("truetype"); }</style><style>@font-face { font-family: "Edunline" ; src: url("fonts/Edunline.ttf") format("truetype"); }</style><script>window.fonts = ["BitCell","Edunline"]</script></head><body class="noselect custom-cursor" oncontextmenu="return false;"><div id="canvaswrapper"></div><script type="text/javascript">var resources = {"images":[{"file":"arrow_left.png","version":11,"size":175,"properties":{"frames":1,"fps":5}},{"file":"arrow_right.png","version":6,"size":177,"properties":{"frames":1,"fps":5}},{"file":"exit.png","version":21,"size":152,"properties":{"frames":1,"fps":5}},{"file":"gamepad.png","version":33,"size":327,"properties":{"frames":1,"fps":5}},{"file":"icon.png","version":250,"size":748,"properties":{"frames":1,"fps":5}},{"file":"icon_transparent.png","version":19,"size":741,"properties":{"frames":1,"fps":5}},{"file":"keyboard.png","version":24,"size":272,"properties":{"frames":1,"fps":5}},{"file":"microstudio.png","version":1,"size":17652,"properties":{}},{"file":"poster.png","version":4,"size":56514,"properties":{"frames":1,"fps":5}},{"file":"rotate.png","version":47,"size":286,"properties":{"frames":1,"fps":5}},{"file":"touch.png","version":25,"size":239,"properties":{"frames":1,"fps":5}}],"assets":[],"maps":{},"sounds":[{"file":"microfxr-back.wav","version":1,"size":51772,"properties":{}},{"file":"microfxr-enter.wav","version":1,"size":51772,"properties":{}},{"file":"microfxr-switch.wav","version":1,"size":4872,"properties":{}},{"file":"microfxr-welcome.wav","version":1,"size":95192,"properties":{}}],"music":[]};
var graphics = "M1";
</script><script type="text/javascript">var orientation = 'landscape' ;
var aspect = 'free' ;
var ms_libs = [] ;
window.skip_service_worker = true;
window.exported_project = true;
window.ms_use_server = false ;
</script><script src="compiler.js"></script><script src="parser.js"></script><script src="processor.js"></script><script src="program.js"></script><script src="routine.js"></script><script src="runner.js"></script><script src="token.js"></script><script src="tokenizer.js"></script><script src="transpiler.js"></script><script src="microengine.js"></script></body><script type="text/javascript">//
//
// The game is started with the code below.
// Once you have received the "started" signal (see below),
// you can do the following:
// 1) Inject functions or objects into the global context of the microStudio engine, example:
//
// window.player.setGlobal("special_callback",function(x) { console.info(x) }) ;
// // Your microScript code can now call the "special_callback" function
//
// 2) Call microScript global functions from your JavaScript code, example:
//
// window.player.call("call_me_from_javascript",[10,1000]) ;
// // arguments to the function call are provided as an array
//
// 3) Run a microScript code snippet from your JavaScript code, example:
//
// window.player.exec("player.position_x = 50",function(result) { console.log(result) ; }) ;
//
window.addEventListener("load",function() {
window.player = new Player(function(event) {
if (event.name == "started") {
// signal that the game is started
}
else if (event.name == "log") {
// console.info(event.data) ;
}
}) ;
document.body.focus() ;
}) ;
</script><script id="code" type="text/x-microscript">
function()
addGame = function(title,nick,slug)
games += object
title = title
nick = nick
slug = slug
end
end
addGames = function()
games = []
addGame("Nameless Moth","Deleted","moth")
addGame("Evade","HomineLudens","evade")
addGame("Take me to Mars","JimB007","tmtm")
addGame("The Great Wyrm","KimsGames","holiday2022")
addGame("micro Mower","JimB007","micromower")
addGame("Lemmy Long Legs II","Ogofkop","lemmylonglegs2")
addGame("Panzer!","Sebastian","panzer")
addGame("Marble Quest","HomineLudens","marblequest")
addGame("Meowy's Adventure","mrLman","meowys_adventure")
addGame("Energy Leak","JmeJuniper","nrgleak2")
addGame("micro Farm","JimB007","microfarm")
addGame("Night Drive","jaysnjj","nightdrive")
addGame("Courage","KimsGames","courage")
addGame("NES Fire","royerson","fire")
addGame("micro Adventure","JimB007","micoadventure")
addGame("Sandra and the Avocados","stonith","sandra")
addGame("Troubles Be Gone","KimsGames","halloween")
addGame("Reggie the Hedgie","gilles","reggie")
addGame("Alien Blaster","jaysnjj","alien_blaster")
addGame("Lemmy Long Legs","Ogofkop","lemmylongleg")
addGame("Fishing Party","gilles","fishing2")
addGame("Racing Demo","gilles","racingdemo")
addGame("Planet Repair Squad","gilles","planetrepairsquad")
shuffle()
end
shuffle = function()
local g = []
while games.length > 0
local game = games.removeAt(random.nextInt(games.length))
g += game
end
games = g
end
end()
system.javascript("""
// javascript
this.embed = function(url,close_button) {
console.info(url);
console.info("close_button = "+close_button)
var canvas = document.querySelector("canvas") ;
var parent = canvas.parentNode ;
var iframe = document.createElement("iframe") ;
iframe.src = url ;
iframe.allow = "autoplay https://microstudio.io; gamepad https://microstudio.io; midi https://microstudio.io"
iframe.style = "position: absolute ; top: 0 ; left: 0 ; width: 100% ; height: 100% ; border: none ; z-index: 0 ; transition-property: opacity ; transition-duration: 2s ; opacity: 0" ;
iframe.allowFullscreen = false ;
canvas.style["transition-property"] = "opacity" ;
canvas.style["transition-duration"] = "1s" ;
parent.insertBefore(iframe,canvas)
iframe.contentWindow.addEventListener("load",()=>{
iframe.contentWindow.focus() ;
iframe.style.opacity = 1 ;
})
iframe.contentWindow.addEventListener('keydown', (event) => {
console.log('Keydown event in iframe:', event);
if (event.key == "Escape") {
global.back_to_menu = true ;
}
});
if (close_button) {
console.info("CLOSE BUTTON")
var img = new Image() ;
img.src = "sprites/exit.png" ;
img.id = "exit-button" ;
img.style = "width: 5vw ; position: fixed ; top: 1.5vw ; right: 1.5vw ; opacity: .5 ; image-rendering: moz-crisp-edges; image-rendering: pixelated ; z-index: 10" ;
document.body.appendChild(img) ;
img.addEventListener("click",()=>{global.back_to_menu = true})
}
setTimeout(()=> {
canvas.style.opacity = 0 ;
setTimeout(()=>{
canvas.style.display = "none" ;
},1000)
},0)
setTimeout(()=>{
},500)
global.canvas = canvas
global.iframe = iframe
global.window = window
}
this.restore = function() {
var iframe = document.querySelector("iframe") ;
if (iframe) {
iframe.parentNode.removeChild(iframe) ;
}
var canvas = document.querySelector("canvas") ;
canvas.style.display = "block" ;
setTimeout(()=>{
canvas.style.opacity = 1 ;
},1)
setTimeout(()=> { window.focus() },100)
var exit = document.getElementById("exit-button") ;
if (exit) {
exit.parentNode.removeChild(exit) ;
}
}
this.loadImage = function(url,callback) {
var img = new Image() ;
img.src = url ;
img.onload = ()=> { callback(new global.Image(img)) } ;
}
var fullscreendone = false ;
document.body.addEventListener("mouseup",()=> {
if (! fullscreendone) {
fullscreendone = true ;
document.body.requestFullscreen() ;
}
}) ;
/*
This will be needed to work cross-domain
window.addEventListener("message",(msg)=>{
try {
var data = JSON.parse(msg.data) ;
if (data.name == "started") {
console.info("STARTED!") ;
}
} catch (err) {
};
}) ;*/
""")
function()
CRT = function(size = 240,intensity = .5)
if not CRT_BUFFER.type or size != CRT_BUFFER_SIZE or intensity != CRT_BUFFER_INTENSITY then
CRT_BUFFER_SIZE = size
size *= 2
CRT_BUFFER_INTENSITY = intensity
CRT_BUFFER = new Image(size,size)
CRT_BUFFER.setRadialGradient(size/2,size/2,size/2*1.4142,"rgba(0,0,0,0)","rgba(0,0,0,"+intensity+")")
CRT_BUFFER.fillRect(0,0,size,size)
CRT_BUFFER.setRadialGradient(size/2,size/2,size/2*3,"rgba(0,0,0,0)","rgba(0,0,0,"+intensity+")")
for i=0 to size by 4
//CRT_BUFFER.drawLine(0,0,200,200)
CRT_BUFFER.drawLine(0,i+.5,size,i+.5)
end
end
screen.setPixelated(false)
screen.drawImage(CRT_BUFFER,0,0,screen.width,screen.height)
screen.setPixelated(true)
end
end()
function()
init = function()
// embed()
addGames()
for game in games
loadImage("https://microstudio.io/"+game.nick+"/"+game.slug+"/sprites/icon.png",function(img)
game.image = img
end)
end
browse_position = 0
browse_selected = 0
target_position = 0
position_speed = 0
started = false
back_to_menu = false
dragging = false
control_modes = ["keyboard","gamepad","touch"]
control = object end
clickable = []
mode = "browse"
screen.setFont("Edunline")
end
update = function()
if not started then
if mouse.press then
started = true
audio.playSound("microfxr/welcome",.125)
end
return
end
if gamepad.press.RIGHT or gamepad.press.LEFT or gamepad.A then
control_modes = ["gamepad"]
end
if keyboard.press.RIGHT or keyboard.press.LEFT or keyboard.press.ENTER or keyboard.press.SPACE then
control_modes = ["keyboard"]
end
control.LEFT = gamepad.press.LEFT or keyboard.press.LEFT
control.RIGHT = gamepad.press.RIGHT or keyboard.press.RIGHT
control.ACTION = gamepad.press.A or keyboard.press.ENTER or keyboard.press.SPACE
control.BACK = back_to_menu or gamepad.press.MENU or (gamepad.X and gamepad.B)
if touch.press then
control_modes = ["touch"]
dragging = false
if abs(touch.x+150)<10 and abs(touch.y)<25 then
if target_position > 0 then
target_position -= 1
browse_selected = target_position+1
audio.playSound("microfxr/switch",.125)
end
elsif abs(touch.x-150)<10 and abs(touch.y)<25 then
if target_position < games.length-4 then
target_position += 1
browse_selected = target_position+1
audio.playSound("microfxr/switch",.125)
end
elsif abs(touch.x)<140 and abs(touch.y)<50 then
dragging = true
drag_start = target_position
drag_start_x = touch.x
drag_moved = false
browse_selected = round((touch.x+105)/70)+target_position
end
end
if touch.touching then
if dragging then
if abs(touch.x - drag_start_x) > 10 then
drag_moved = true
browse_selected = -1
end
if drag_moved then
target_position = max(0,min(games.length-4,drag_start+(drag_start_x-touch.x)/30))
end
end
end
if touch.release then
if dragging then
dragging = false
if drag_moved then
target_position = round(target_position)
browse_selected = target_position + 1
else
control.ACTION = true
end
end
end
if mode == "browse" then
if control.RIGHT then
if browse_selected < games.length-1 then
browse_selected += 1
audio.playSound("microfxr/switch",.125)
if target_position < browse_selected-2 then
target_position += 1
target_position = min(games.length-4,target_position)
end
end
end
if (control.LEFT) and browse_selected > 0 then
browse_selected -= 1
audio.playSound("microfxr/switch",.125)
if target_position > browse_selected-1 and target_position > 0 then
target_position -= 1
end
end
if control.ACTION then
mode = "play"
audio.playSound("microfxr/enter",.125)
local game = games[browse_selected]
embed("https://microstudio.io/"+game.nick+"/"+game.slug+"/",control_modes[0] == "touch")
end
else
if control.BACK then
back_to_menu = false
restore()
mode = "browse"
audio.playSound("microfxr/back",.125)
end
end
position_speed += (target_position-browse_position)*.1
position_speed *= .5
browse_position += position_speed
end
draw = function()
local background = "rgb(5,30,43)"
screen.clear(background)
if screen.width < screen.height then
screen.setAlpha(.5)
screen.drawSprite("rotate",0,0,48)
screen.setAlpha(1)
return
end
screen.setFont("Edunline")
if not screen.isFontReady() then
return
end
screen.drawText("micro Box",0,65,20,"rgb(65,120,147)")
if not started then
screen.setFont("BitCell")
local size = sin((system.time()%500)/500*PI*2)
screen.fillRect(0,-25,60+size,18+size*.5,"rgb(197,87,87)")
screen.drawText("START",0,-25,10,"#FFF")
screen.drawSprite("icon_transparent",0,20)
screen.drawText("Powered by",0,-70,6,"rgba(255,255,255,.5)")
screen.setPixelated(false)
screen.drawSprite("microstudio",0,-80,50)
screen.setPixelated(true)
return
end
// screen.drawSprite("icon",-120,65,20)
screen.setFont("BitCell")
for i=0 to games.length-1 by 1
local game = games[i]
local x = (i-browse_position)*70-105
if game and game.image and abs(x) <160 then
screen.setAlpha(max(0,min(1,3-abs(x)/160*3)))
if i == browse_selected then
screen.fillRect(x,0,55,55,"rgb(255,142,85)")
screen.fillRect(x,0,51,51,background)
else
screen.fillRect(x,0,55,55,"rgba(255,255,255,.1)")
end
screen.drawSprite(game.image,x,0,50,50)
screen.drawText(game.title,x,-35,7,"rgba(255,255,255,.8)")
end
end
screen.setAlpha(.5)
if target_position > 0 then
screen.drawSprite("arrow_left",-150,0,8)
end
if target_position < games.length-4 then
screen.drawSprite("arrow_right",150,0,8)
end
local dx = -(control_modes.length-1)/2*50
for c in control_modes
screen.drawSprite(c,dx,-65,24)
dx += 50
end
if control_modes.length == 1 then
if control_modes[0] == "keyboard" then
screen.drawText("ENTER to start game - ESC to exit game",0,-90,8)
elsif control_modes[0] == "gamepad" then
screen.drawText("[A] to start game - [MENU] to exit game",0,-90,8)
else
screen.drawText("Tap to start game",-50,-90,8)
screen.drawText("exit game with",50,-90,8)
screen.setAlpha(1)
screen.drawSprite("exit",85,-90)
end
end
screen.setAlpha(1)
// CRT()
end
end()
</script></html>
@@ -0,0 +1,33 @@
{
"name": "micro Box",
"short_name": "micro Box",
"theme_color": "#000000",
"background_color": "#000000",
"display": "fullscreen",
"orientation": "landscape",
"scope": "",
"start_url": ".",
"icons": [
{
"src": "icon192.png?v=0",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "icon196.png?v=0",
"type": "image/png",
"sizes": "196x196",
"purpose": "maskable"
},
{
"src": "icon512.png?v=0",
"type": "image/png",
"sizes": "512x512"
},
{
"src": "icon1024.png?v=0",
"type": "image/png",
"sizes": "1024x1024"
}
]
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,812 @@
this.Parser = (function() {
class Parser {
constructor(input, filename = "") {
this.input = input;
this.filename = filename;
if (/^\s*\/\/\s*javascript\s*\n/.test(this.input)) {
this.input = 'system.javascript("""\n\n' + this.input.replace(/\\/g, "\\\\") + '\n\n""")';
}
this.tokenizer = new Tokenizer(this.input, this.filename);
this.program = new Program();
this.current_block = [];
this.current = {
line: 1,
column: 1
};
this.verbose = false;
this.nesting = 0;
this.object_nesting = 0;
this.not_terminated = [];
this.api_reserved = {
screen: true,
audio: true,
keyboard: true,
gamepad: true,
sprites: true,
sounds: true,
music: true,
assets: true,
asset_manager: true,
maps: true,
touch: true,
mouse: true,
fonts: true,
Sound: true,
Image: true,
Sprite: true,
Map: true,
system: true,
storage: true,
print: true,
random: true,
Function: true,
List: true,
Object: true,
String: true,
Number: true
};
}
nextToken() {
var token;
token = this.tokenizer.next();
if (token == null) {
this.unexpected_eof = true;
throw "Unexpected end of file";
}
return this.current = token;
}
nextTokenOptional() {
var token;
token = this.tokenizer.next();
if (token != null) {
this.current = token;
}
return token;
}
parse() {
var err, expression, nt, token;
try {
this.warnings = [];
while (true) {
expression = this.parseLine();
if ((expression == null) && !this.tokenizer.finished()) {
token = this.tokenizer.next();
if ((token != null) && token.reserved_keyword) {
if (token.value === "end") {
this.error("Too many 'end'");
} else {
this.error(`Misuse of reserved keyword: '${token.value}'`);
}
} else {
this.error("Unexpected data");
}
}
if (expression === null) {
break;
}
this.current_block.push(expression);
this.program.add(expression);
if (this.verbose) {
console.info(expression);
}
}
return this;
} catch (error1) {
err = error1;
//console.info "Error at line: #{@current.line} column: #{@current.column}"
if (this.not_terminated.length > 0 && err === "Unexpected end of file") {
nt = this.not_terminated[this.not_terminated.length - 1];
return this.error_info = {
error: `Unterminated '${nt.value}' ; no matching 'end' found`,
line: nt.line,
column: nt.column
};
} else {
return this.error_info = {
error: err,
line: this.current.line,
column: this.current.column
};
}
}
}
//console.error err
parseLine() {
var token;
token = this.nextTokenOptional();
if (token == null) {
return null;
}
switch (token.type) {
case Token.TYPE_RETURN:
return new Program.Return(token, this.parseExpression());
case Token.TYPE_BREAK:
return new Program.Break(token);
case Token.TYPE_CONTINUE:
return new Program.Continue(token);
case Token.TYPE_LOCAL:
return this.parseLocalAssignment(token);
default:
this.tokenizer.pushBack(token);
return this.parseExpression();
}
}
parseExpression(filter, first_function_call = false) {
var access, expression;
expression = this.parseExpressionStart();
if (expression == null) {
return null;
}
while (true) {
access = this.parseExpressionSuffix(expression, filter);
if (access == null) {
return expression;
}
if (first_function_call && access instanceof Program.FunctionCall) {
return access;
}
expression = access;
}
}
assertExpression(filter, first_function_call = false) {
var exp;
exp = this.parseExpression(filter, first_function_call);
if (exp == null) {
throw "Expression expected";
}
return exp;
}
parseExpressionSuffix(expression, filter) {
var field, identifier, token;
token = this.nextTokenOptional();
if (token == null) {
return (filter === "self" ? expression : null);
}
switch (token.type) {
case Token.TYPE_DOT:
if (expression instanceof Program.Value && expression.type === Program.Value.TYPE_NUMBER) {
this.tokenizer.pushBack(token);
return null;
} else {
this.tokenizer.changeNumberToIdentifier();
identifier = this.assertBroadIdentifier("Expected identifier");
return Program.CreateFieldAccess(token, expression, new Program.Value(identifier, Program.Value.TYPE_STRING, identifier.value));
}
break;
case Token.TYPE_OPEN_BRACKET:
field = this.assertExpression();
this.assert(Token.TYPE_CLOSED_BRACKET, "Expected ']'");
return Program.CreateFieldAccess(token, expression, field);
case Token.TYPE_OPEN_BRACE:
return this.parseFunctionCall(token, expression);
case Token.TYPE_EQUALS:
return this.parseAssignment(token, expression);
case Token.TYPE_PLUS_EQUALS:
return this.parseSelfAssignment(token, expression, token.type);
case Token.TYPE_MINUS_EQUALS:
return this.parseSelfAssignment(token, expression, token.type);
case Token.TYPE_MULTIPLY_EQUALS:
return this.parseSelfAssignment(token, expression, token.type);
case Token.TYPE_DIVIDE_EQUALS:
return this.parseSelfAssignment(token, expression, token.type);
case Token.TYPE_MODULO_EQUALS:
case Token.TYPE_AND_EQUALS:
case Token.TYPE_OR_EQUALS:
return this.parseSelfAssignment(token, expression, token.type);
default:
if (filter === "self") {
this.tokenizer.pushBack(token);
return expression;
} else if (token.is_binary_operator && filter !== "noop") {
return this.parseBinaryOperation(token, expression);
} else {
this.tokenizer.pushBack(token);
return null;
}
}
}
parseExpressionStart() {
var next, token;
token = this.nextTokenOptional();
if (token == null) {
return null;
}
switch (token.type) {
case Token.TYPE_IDENTIFIER: // variable name
return new Program.Variable(token, token.value);
case Token.TYPE_NUMBER:
return this.parseNumberExpression(token);
case Token.TYPE_PLUS:
return this.assertExpression();
case Token.TYPE_MINUS:
return this.parseExpressionSuffix(new Program.Negate(token, this.assertExpression("noop")), "self");
case Token.TYPE_NOT:
return this.parseExpressionSuffix(new Program.Not(token, this.assertExpression("noop")), "self");
case Token.TYPE_STRING:
return this.parseStringExpression(token);
case Token.TYPE_IF:
return this.parseIf(token);
case Token.TYPE_FOR:
return this.parseFor(token);
case Token.TYPE_WHILE:
return this.parseWhile(token);
case Token.TYPE_OPEN_BRACE:
return this.parseBracedExpression(token);
case Token.TYPE_OPEN_BRACKET:
return this.parseArray(token);
case Token.TYPE_FUNCTION:
return this.parseFunction(token);
case Token.TYPE_OBJECT:
return this.parseObject(token);
case Token.TYPE_CLASS:
return this.parseClass(token);
case Token.TYPE_NEW:
return this.parseNew(token);
case Token.TYPE_DOT:
next = this.assert(Token.TYPE_NUMBER, "malformed number");
if (!Number.isInteger(next.value)) {
throw "malformed number";
}
return new Program.Value(token, Program.Value.TYPE_NUMBER, Number.parseFloat(`.${next.string_value}`));
case Token.TYPE_AFTER:
return this.parseAfter(token);
case Token.TYPE_EVERY:
return this.parseEvery(token);
case Token.TYPE_DO:
return this.parseDo(token);
case Token.TYPE_SLEEP:
return this.parseSleep(token);
case Token.TYPE_DELETE:
return this.parseDelete(token);
default:
this.tokenizer.pushBack(token);
return null;
}
}
parseNumberExpression(number) {
return new Program.Value(number, Program.Value.TYPE_NUMBER, number.value);
}
parseStringExpression(string) {
var token;
token = this.nextTokenOptional();
if (token == null) {
return new Program.Value(string, Program.Value.TYPE_STRING, string.value);
} else {
this.tokenizer.pushBack(token);
return new Program.Value(string, Program.Value.TYPE_STRING, string.value);
}
}
parseArray(bracket) {
var res, token;
res = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_CLOSED_BRACKET) {
return new Program.Value(bracket, Program.Value.TYPE_ARRAY, res);
} else if (token.type === Token.TYPE_COMMA) {
continue;
} else {
this.tokenizer.pushBack(token);
res.push(this.assertExpression());
}
}
}
parseBinaryOperation(operation, term1) {
var ops, terms, token;
ops = [new Program.Operation(operation, operation.value)];
terms = [term1];
terms.push(this.assertExpression("noop"));
while (true) {
token = this.nextTokenOptional();
if (token == null) {
break;
}
if (!token.is_binary_operator) {
this.tokenizer.pushBack(token);
break;
}
ops.push(new Program.Operation(token, token.value));
terms.push(this.assertExpression("noop"));
}
return Program.BuildOperations(ops, terms);
}
parseAssignment(token, expression) {
var res;
if (!(expression instanceof Program.Variable) && !(expression instanceof Program.Field)) {
throw "Expected variable identifier or property";
}
if (this.object_nesting === 0 && expression instanceof Program.Variable && this.api_reserved[expression.identifier]) {
this.warnings.push({
type: "assigning_api_variable",
identifier: expression.identifier,
line: token.line,
column: token.column
});
}
if (expression instanceof Program.Field) {
this.object_nesting += 1;
res = new Program.Assignment(token, expression, this.assertExpression());
this.object_nesting -= 1;
} else {
res = new Program.Assignment(token, expression, this.assertExpression());
}
return res;
}
parseSelfAssignment(token, expression, operation) {
if (!(expression instanceof Program.Variable) && !(expression instanceof Program.Field)) {
throw "Expected variable identifier or property";
}
return new Program.SelfAssignment(token, expression, operation, this.assertExpression());
}
parseLocalAssignment(local) {
var identifier;
identifier = this.assert(Token.TYPE_IDENTIFIER, "Expected identifier");
this.assert(Token.TYPE_EQUALS, "Expected '='");
return new Program.Assignment(local, new Program.Variable(identifier, identifier.value), this.assertExpression(), true);
}
parseBracedExpression(open) {
var expression, token;
expression = this.assertExpression();
token = this.nextToken();
if (token.type === Token.TYPE_CLOSED_BRACE) {
return new Program.Braced(open, expression);
} else {
return this.error("missing closing parenthese");
}
}
parseFunctionCall(brace_token, expression) {
var args, start, token;
args = [];
this.last_function_call = new Program.FunctionCall(brace_token, expression, args);
this.last_function_call.argslimits = [];
while (true) {
token = this.nextTokenOptional();
if (token == null) {
return this.error("missing closing parenthese");
} else if (token.type === Token.TYPE_CLOSED_BRACE) {
return new Program.FunctionCall(token, expression, args);
} else if (token.type === Token.TYPE_COMMA) {
continue;
} else {
this.tokenizer.pushBack(token);
start = token.start;
args.push(this.assertExpression());
this.last_function_call.argslimits.push({
start: start,
end: this.tokenizer.index - 1
});
}
}
}
addTerminable(token) {
return this.not_terminated.push(token);
}
endTerminable() {
if (this.not_terminated.length > 0) {
this.not_terminated.splice(this.not_terminated.length - 1, 1);
}
}
parseFunction(funk) {
var args, line, sequence, token;
this.nesting += 1;
this.addTerminable(funk);
args = this.parseFunctionArgs();
sequence = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.endTerminable();
return new Program.Function(funk, args, sequence, token);
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line != null) {
sequence.push(line);
} else {
this.error("Unexpected data while parsing function");
}
}
}
}
parseFunctionArgs() {
var args, exp, last, token;
token = this.nextToken();
args = [];
last = null;
if (token.type !== Token.TYPE_OPEN_BRACE) {
return this.error("Expected opening parenthese");
}
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_CLOSED_BRACE) {
return args;
} else if (token.type === Token.TYPE_COMMA) {
last = null;
continue;
} else if (token.type === Token.TYPE_EQUALS && last === "argument") {
exp = this.assertExpression();
args[args.length - 1].default = exp;
} else if (token.type === Token.TYPE_IDENTIFIER) {
last = "argument";
args.push({
name: token.value
});
} else {
return this.error("Unexpected token");
}
}
}
warningAssignmentCondition(expression) {
if (expression instanceof Program.Assignment) {
return this.warnings.push({
type: "assignment_as_condition",
line: expression.token.line,
column: expression.token.column
});
}
}
parseIf(iftoken) {
var chain, current, line, token;
this.addTerminable(iftoken);
current = {
condition: this.assertExpression(),
sequence: []
};
this.warningAssignmentCondition(current.condition);
chain = [];
token = this.nextToken();
if (token.type !== Token.TYPE_THEN) {
return this.error("Expected 'then'");
}
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_ELSIF) {
chain.push(current);
current = {
condition: this.assertExpression(),
sequence: []
};
this.warningAssignmentCondition(current.condition);
this.assert(Token.TYPE_THEN, "Expected 'then'");
} else if (token.type === Token.TYPE_ELSE) {
current.else = [];
} else if (token.type === Token.TYPE_END) {
chain.push(current);
this.endTerminable();
return new Program.Condition(iftoken, chain);
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line == null) {
throw Error("Unexpected data while parsing if");
}
if (current.else != null) {
current.else.push(line);
} else {
current.sequence.push(line);
}
}
}
}
assert(type, error) {
var token;
token = this.nextToken();
if (token.type !== type) {
throw error;
}
return token;
}
assertBroadIdentifier(error) {
var token;
token = this.nextToken();
if (token.type !== Token.TYPE_IDENTIFIER && token.reserved_keyword) {
token.type = Token.TYPE_IDENTIFIER;
}
if (token.type !== Token.TYPE_IDENTIFIER) {
throw error;
}
return token;
}
error(text) {
throw text;
}
parseFor(fortoken) {
var iterator, list, range_by, range_from, range_to, token;
iterator = this.assertExpression();
if (iterator instanceof Program.Assignment) {
range_from = iterator.expression;
iterator = iterator.field;
token = this.nextToken();
if (token.type !== Token.TYPE_TO) {
return this.error("Expected 'to'");
}
range_to = this.assertExpression();
token = this.nextToken();
if (token.type === Token.TYPE_BY) {
range_by = this.assertExpression();
} else {
range_by = 0;
this.tokenizer.pushBack(token);
}
return new Program.For(fortoken, iterator.identifier, range_from, range_to, range_by, this.parseSequence(fortoken));
} else if (iterator instanceof Program.Variable) {
this.assert(Token.TYPE_IN, "Error expected keyword 'in'");
list = this.assertExpression();
return new Program.ForIn(fortoken, iterator.identifier, list, this.parseSequence(fortoken));
} else {
return this.error("Malformed for loop");
}
}
parseWhile(whiletoken) {
var condition;
condition = this.assertExpression();
return new Program.While(whiletoken, condition, this.parseSequence(whiletoken));
}
parseSequence(start_token) {
var line, sequence, token;
if (start_token != null) {
this.addTerminable(start_token);
}
this.nesting += 1;
sequence = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
if (start_token != null) {
this.endTerminable();
}
this.nesting -= 1;
return sequence;
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line == null) {
this.error("Unexpected data");
}
sequence.push(line);
}
}
return sequence;
}
parseObject(object) {
var exp, fields, token;
this.nesting += 1;
this.object_nesting += 1;
this.addTerminable(object);
fields = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.object_nesting -= 1;
this.endTerminable();
return new Program.CreateObject(object, fields);
} else {
if (token.type !== Token.TYPE_IDENTIFIER && token.reserved_keyword) {
token.type = Token.TYPE_IDENTIFIER;
}
if (token.type === Token.TYPE_STRING) {
token.type = Token.TYPE_IDENTIFIER;
}
if (token.type === Token.TYPE_IDENTIFIER) {
this.assert(Token.TYPE_EQUALS, "Expected '='");
exp = this.assertExpression();
fields.push({
field: token.value,
value: exp
});
} else {
return this.error("Malformed object");
}
}
}
}
parseClass(object) {
var exp, ext, fields, token;
this.nesting += 1;
this.object_nesting += 1;
this.addTerminable(object);
fields = [];
token = this.nextToken();
if (token.type === Token.TYPE_EXTENDS) {
ext = this.assertExpression();
token = this.nextToken();
}
while (true) {
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.object_nesting -= 1;
this.endTerminable();
return new Program.CreateClass(object, ext, fields);
} else {
if (token.type !== Token.TYPE_IDENTIFIER && token.reserved_keyword) {
token.type = Token.TYPE_IDENTIFIER;
}
if (token.type === Token.TYPE_STRING) {
token.type = Token.TYPE_IDENTIFIER;
}
if (token.type === Token.TYPE_IDENTIFIER) {
this.assert(Token.TYPE_EQUALS, "Expected '='");
exp = this.assertExpression();
fields.push({
field: token.value,
value: exp
});
} else {
return this.error("Malformed object");
}
}
token = this.nextToken();
}
}
parseNew(token) {
var exp;
exp = this.assertExpression(null, true);
return new Program.NewCall(token, exp);
}
parseAfter(after) {
var delay, line, multiplier, sequence, token;
this.nesting += 1;
this.addTerminable(after);
delay = this.assertExpression();
token = this.nextToken();
multiplier = null;
if (token.type === Token.TYPE_IDENTIFIER && this.multipliers[token.value]) {
multiplier = this.multipliers[token.value];
token = this.nextToken();
}
if ((token == null) || token.type !== Token.TYPE_DO) {
this.error("Expected keyword 'do'");
}
sequence = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.endTerminable();
return new Program.After(after, delay, sequence, token, multiplier);
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line != null) {
sequence.push(line);
} else {
this.error("Unexpected data while parsing after");
}
}
}
}
parseEvery(every) {
var delay, line, multiplier, sequence, token;
this.nesting += 1;
this.addTerminable(every);
delay = this.assertExpression();
token = this.nextToken();
multiplier = null;
if (token.type === Token.TYPE_IDENTIFIER && this.multipliers[token.value]) {
multiplier = this.multipliers[token.value];
token = this.nextToken();
}
if ((token == null) || token.type !== Token.TYPE_DO) {
this.error("Expected keyword 'do'");
}
sequence = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.endTerminable();
return new Program.Every(every, delay, sequence, token, multiplier);
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line != null) {
sequence.push(line);
} else {
this.error("Unexpected data while parsing after");
}
}
}
}
parseDo(do_token) {
var line, sequence, token;
this.nesting += 1;
this.addTerminable(do_token);
sequence = [];
while (true) {
token = this.nextToken();
if (token.type === Token.TYPE_END) {
this.nesting -= 1;
this.endTerminable();
return new Program.Do(do_token, sequence, token);
} else {
this.tokenizer.pushBack(token);
line = this.parseLine();
if (line != null) {
sequence.push(line);
} else {
this.error("Unexpected data while parsing after");
}
}
}
}
parseSleep(sleep) {
var delay, multiplier, token;
delay = this.assertExpression();
token = this.nextToken();
multiplier = null;
if (token != null) {
if (token.type === Token.TYPE_IDENTIFIER && this.multipliers[token.value]) {
multiplier = this.multipliers[token.value];
} else {
this.tokenizer.pushBack(token);
}
}
return new Program.Sleep(sleep, delay, multiplier);
}
parseDelete(del) {
var v;
v = this.parseExpression();
if ((v == null) || (!(v instanceof Program.Variable) && !(v instanceof Program.Field))) {
return this.error("expecting variable name or property access after keyword `delete`");
} else {
return new Program.Delete(del, v);
}
}
};
Parser.prototype.multipliers = {
millisecond: 1,
milliseconds: 1,
second: 1000,
seconds: 1000,
minute: 60000,
minutes: 60000,
hour: 60000 * 60,
hours: 60000 * 60,
day: 60000 * 60 * 24,
days: 60000 * 60 * 24
};
return Parser;
}).call(this);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,371 @@
this.Program = class Program {
constructor() {
this.statements = [];
}
add(statement) {
return this.statements.push(statement);
}
isAssignment() {
return this.statements.length > 0 && this.statements[this.statements.length - 1] instanceof Program.Assignment;
}
};
this.Program.Expression = class Expression {
constructor() {}
};
this.Program.Assignment = class Assignment {
constructor(token1, field1, expression1, local) {
this.token = token1;
this.field = field1;
this.expression = expression1;
this.local = local;
}
};
this.Program.SelfAssignment = class SelfAssignment {
constructor(token1, field1, operation, expression1) {
this.token = token1;
this.field = field1;
this.operation = operation;
this.expression = expression1;
}
};
this.Program.Value = (function() {
class Value {
constructor(token1, type, value1) {
this.token = token1;
this.type = type;
this.value = value1;
}
};
Value.TYPE_NUMBER = 1;
Value.TYPE_STRING = 2;
Value.TYPE_ARRAY = 3;
Value.TYPE_OBJECT = 4;
Value.TYPE_FUNCTION = 5;
Value.TYPE_CLASS = 6;
return Value;
}).call(this);
this.Program.CreateFieldAccess = function(token, expression, field) {
if (expression instanceof Program.Field) {
expression.appendField(field);
return expression;
} else {
return new Program.Field(token, expression, [field]);
}
};
this.Program.Variable = class Variable {
constructor(token1, identifier) {
this.token = token1;
this.identifier = identifier;
}
};
this.Program.Field = class Field {
constructor(token1, expression1, chain) {
this.token = token1;
this.expression = expression1;
this.chain = chain;
this.token = this.expression.token;
}
appendField(field) {
return this.chain.push(field);
}
};
this.Program.BuildOperations = function(ops, terms) {
var i, o, o1, o2, prec, t1, t2;
while (ops.length > 1) {
i = 0;
prec = 0;
while (i < ops.length - 1) {
o1 = ops[i];
o2 = ops[i + 1];
if (Program.Precedence[o2.operation] <= Program.Precedence[o1.operation]) {
break;
}
i++;
}
t1 = terms[i];
t2 = terms[i + 1];
o = new Program.Operation(ops[i].token, ops[i].operation, t1, t2);
terms.splice(i, 2, o);
ops.splice(i, 1);
}
return new Program.Operation(ops[0].token, ops[0].operation, terms[0], terms[1]);
};
this.Program.Operation = class Operation {
constructor(token1, operation, term1, term2) {
this.token = token1;
this.operation = operation;
this.term1 = term1;
this.term2 = term2;
}
};
this.Program.Negate = class Negate {
constructor(token1, expression1) {
this.token = token1;
this.expression = expression1;
}
};
this.Program.Not = class Not {
constructor(token1, expression1) {
this.token = token1;
this.expression = expression1;
}
};
this.Program.Braced = class Braced {
constructor(token1, expression1) {
this.token = token1;
this.expression = expression1;
}
};
this.Program.Return = class Return {
constructor(token1, expression1) {
this.token = token1;
this.expression = expression1;
}
};
this.Program.Condition = class Condition {
constructor(token1, chain) {
this.token = token1;
this.chain = chain;
}
};
this.Program.For = class For {
constructor(token1, iterator, range_from, range_to, range_by, sequence) {
this.token = token1;
this.iterator = iterator;
this.range_from = range_from;
this.range_to = range_to;
this.range_by = range_by;
this.sequence = sequence;
}
};
this.Program.ForIn = class ForIn {
constructor(token1, iterator, list, sequence) {
this.token = token1;
this.iterator = iterator;
this.list = list;
this.sequence = sequence;
}
};
this.Program.toString = function(value, nesting = 0) {
var i, j, k, key, len, pref, ref, s, v;
if (value instanceof Routine) {
if (nesting === 0) {
return value.source || "[function]";
} else {
return "[function]";
}
} else if (typeof value === "function") {
return "[native function]";
} else if (typeof value === "string") {
return `"${value}"`;
} else if (Array.isArray(value)) {
if (nesting >= 1) {
return "[list]";
}
s = "[";
for (i = j = 0, len = value.length; j < len; i = ++j) {
v = value[i];
s += Program.toString(v, nesting + 1) + (i < value.length - 1 ? "," : "");
}
return s + "]";
} else if (typeof value === "object") {
if (nesting >= 1) {
return "[object]";
}
s = "object\n";
pref = "";
for (i = k = 1, ref = nesting; k <= ref; i = k += 1) {
pref += " ";
}
for (key in value) {
v = value[key];
s += pref + ` ${key} = ${Program.toString(v, nesting + 1)}\n`;
}
return s + pref + "end";
}
return value || 0;
};
this.Program.While = class While {
constructor(token1, condition, sequence) {
this.token = token1;
this.condition = condition;
this.sequence = sequence;
}
};
this.Program.Break = class Break {
constructor(token1) {
this.token = token1;
this.nopop = true;
}
};
this.Program.Continue = class Continue {
constructor(token1) {
this.token = token1;
this.nopop = true;
}
};
this.Program.Function = class Function {
constructor(token1, args, sequence, end) {
this.token = token1;
this.args = args;
this.sequence = sequence;
this.source = "function" + this.token.tokenizer.input.substring(this.token.index, end.index + 2);
}
};
this.Program.FunctionCall = class FunctionCall {
constructor(token1, expression1, args) {
this.token = token1;
this.expression = expression1;
this.args = args;
}
};
this.Program.CreateObject = class CreateObject {
constructor(token1, fields) {
this.token = token1;
this.fields = fields;
}
};
this.Program.CreateClass = class CreateClass {
constructor(token1, ext, fields) {
this.token = token1;
this.ext = ext;
this.fields = fields;
}
};
this.Program.NewCall = class NewCall {
constructor(token1, expression1) {
this.token = token1;
this.expression = expression1;
if (!(this.expression instanceof Program.FunctionCall)) {
this.expression = new Program.FunctionCall(this.token, this.expression, []);
}
}
};
this.Program.After = class After {
constructor(token1, delay, sequence, end, multiplier) {
this.token = token1;
this.delay = delay;
this.sequence = sequence;
this.multiplier = multiplier;
this.source = "after " + this.token.tokenizer.input.substring(this.token.index, end.index + 2);
}
};
this.Program.Every = class Every {
constructor(token1, delay, sequence, end, multiplier) {
this.token = token1;
this.delay = delay;
this.sequence = sequence;
this.multiplier = multiplier;
this.source = "every " + this.token.tokenizer.input.substring(this.token.index, end.index + 2);
}
};
this.Program.Do = class Do {
constructor(token1, sequence, end) {
this.token = token1;
this.sequence = sequence;
this.source = "do " + this.token.tokenizer.input.substring(this.token.index, end.index + 2);
}
};
this.Program.Sleep = class Sleep {
constructor(token1, delay, multiplier) {
this.token = token1;
this.delay = delay;
this.multiplier = multiplier;
}
};
this.Program.Delete = class Delete {
constructor(token1, field1) {
this.token = token1;
this.field = field1;
}
};
this.Program.Precedence = {
"^": 21,
"/": 20,
"*": 19,
"%": 18,
"+": 17,
"-": 17,
"<": 16,
"<=": 15,
">": 14,
">=": 13,
"==": 12,
"!=": 11,
"<<": 10,
">>": 9,
"&": 8,
"|": 7,
"and": 6,
"or": 5
};
@@ -0,0 +1,530 @@
this.Routine = class Routine {
constructor(num_args) {
this.num_args = num_args;
this.ops = [];
this.opcodes = [];
this.arg1 = [];
this.ref = [];
this.label_count = 0;
this.labels = {};
this.transpile = false;
this.import_refs = [];
this.import_values = [];
this.import_self = -1;
}
clone() {
var r;
r = new Routine(this.num_args);
r.opcodes = this.opcodes;
r.arg1 = this.arg1;
r.ref = this.ref;
r.locals_size = this.locals_size;
r.uses_arguments = this.uses_arguments;
return r;
}
createLabel(str = "label") {
var name;
return name = ":" + str + "_" + this.label_count++;
}
setLabel(name) {
return this.labels[name] = this.opcodes.length;
}
optimize() {
if (this.transpile) {
new Transpiler().transpile(this);
}
}
removeable(index) {
var label, ref1, value;
ref1 = this.labels;
for (label in ref1) {
value = ref1[label];
if (value === index) {
return false;
}
}
return true;
}
remove(index) {
var label, ref1, value;
ref1 = this.labels;
for (label in ref1) {
value = ref1[label];
if (value === index) {
return false;
} else if (value > index) {
this.labels[label] -= 1;
}
}
this.opcodes.splice(index, 1);
this.arg1.splice(index, 1);
this.ref.splice(index, 1);
return true;
}
resolveLabels() {
var i, j, ref1, ref2, ref3, results;
results = [];
for (i = j = 0, ref1 = this.opcodes.length - 1; (0 <= ref1 ? j <= ref1 : j >= ref1); i = 0 <= ref1 ? ++j : --j) {
if ((ref2 = this.opcodes[i]) === OPCODES.JUMP || ref2 === OPCODES.JUMPY || ref2 === OPCODES.JUMPN || ref2 === OPCODES.JUMPY_NOPOP || ref2 === OPCODES.JUMPN_NOPOP) {
if (this.labels[this.arg1[i]]) {
results.push(this.arg1[i] = this.labels[this.arg1[i]]);
} else {
results.push(void 0);
}
} else if ((ref3 = this.opcodes[i]) === OPCODES.FORLOOP_CONTROL || ref3 === OPCODES.FORLOOP_INIT || ref3 === OPCODES.FORIN_CONTROL || ref3 === OPCODES.FORIN_INIT) {
if (this.labels[this.arg1[i][1]]) {
results.push(this.arg1[i][1] = this.labels[this.arg1[i][1]]);
} else {
results.push(void 0);
}
} else {
results.push(void 0);
}
}
return results;
}
OP(code, ref, v1 = 0) {
this.opcodes.push(code);
this.arg1.push(v1);
return this.ref.push(ref);
}
OP_INSERT(code, ref, v1 = 0, index) {
var label, ref1, value;
this.opcodes.splice(index, 0, code);
this.arg1.splice(index, 0, v1);
this.ref.splice(index, 0, ref);
ref1 = this.labels;
for (label in ref1) {
value = ref1[label];
if (value >= index) {
this.labels[label] += 1;
}
}
}
TYPE(ref) {
return this.OP(OPCODES.TYPE, ref);
}
VARIABLE_TYPE(variable, ref) {
return this.OP(OPCODES.VARIABLE_TYPE, ref, variable);
}
PROPERTY_TYPE(ref) {
return this.OP(OPCODES.PROPERTY_TYPE, ref);
}
LOAD_THIS(ref) {
return this.OP(OPCODES.LOAD_THIS, ref);
}
LOAD_GLOBAL(ref) {
return this.OP(OPCODES.LOAD_GLOBAL, ref);
}
LOAD_VALUE(value, ref) {
return this.OP(OPCODES.LOAD_VALUE, ref, value);
}
LOAD_LOCAL(index, ref) {
return this.OP(OPCODES.LOAD_LOCAL, ref, index);
}
LOAD_VARIABLE(variable, ref) {
return this.OP(OPCODES.LOAD_VARIABLE, ref, variable);
}
LOAD_LOCAL_OBJECT(index, ref) {
return this.OP(OPCODES.LOAD_LOCAL_OBJECT, ref, index);
}
LOAD_VARIABLE_OBJECT(variable, ref) {
return this.OP(OPCODES.LOAD_VARIABLE_OBJECT, ref, variable);
}
POP(ref) {
return this.OP(OPCODES.POP, ref);
}
LOAD_PROPERTY(ref) {
return this.OP(OPCODES.LOAD_PROPERTY, ref);
}
LOAD_PROPERTY_OBJECT(ref) {
return this.OP(OPCODES.LOAD_PROPERTY_OBJECT, ref);
}
CREATE_OBJECT(ref) {
return this.OP(OPCODES.CREATE_OBJECT, ref);
}
MAKE_OBJECT(ref) {
return this.OP(OPCODES.MAKE_OBJECT, ref);
}
CREATE_ARRAY(ref) {
return this.OP(OPCODES.CREATE_ARRAY, ref);
}
CREATE_CLASS(parent_var, ref) {
return this.OP(OPCODES.CREATE_CLASS, ref, parent_var);
}
UPDATE_CLASS(variable, ref) {
return this.OP(OPCODES.UPDATE_CLASS, ref, variable);
}
NEW_CALL(args, ref) {
return this.OP(OPCODES.NEW_CALL, ref, args);
}
ADD(ref, self = 0) {
return this.OP(OPCODES.ADD, ref, self);
}
SUB(ref, self = 0) {
return this.OP(OPCODES.SUB, ref, self);
}
MUL(ref) {
return this.OP(OPCODES.MUL, ref);
}
DIV(ref) {
return this.OP(OPCODES.DIV, ref);
}
MODULO(ref) {
return this.OP(OPCODES.MODULO, ref);
}
BINARY_AND(ref) {
return this.OP(OPCODES.BINARY_AND, ref);
}
BINARY_OR(ref) {
return this.OP(OPCODES.BINARY_OR, ref);
}
SHIFT_LEFT(ref) {
return this.OP(OPCODES.SHIFT_LEFT, ref);
}
SHIFT_RIGHT(ref) {
return this.OP(OPCODES.SHIFT_RIGHT, ref);
}
NEGATE(ref) {
return this.OP(OPCODES.NEGATE, ref);
}
LOAD_PROPERTY_ATOP(ref) {
return this.OP(OPCODES.LOAD_PROPERTY_ATOP, ref);
}
EQ(ref) {
return this.OP(OPCODES.EQ, ref);
}
NEQ(ref) {
return this.OP(OPCODES.NEQ, ref);
}
LT(ref) {
return this.OP(OPCODES.LT, ref);
}
GT(ref) {
return this.OP(OPCODES.GT, ref);
}
LTE(ref) {
return this.OP(OPCODES.LTE, ref);
}
GTE(ref) {
return this.OP(OPCODES.GTE, ref);
}
NOT(ref) {
return this.OP(OPCODES.NOT, ref);
}
FORLOOP_INIT(iterator, ref) {
return this.OP(OPCODES.FORLOOP_INIT, ref, iterator);
}
FORLOOP_CONTROL(args, ref) {
return this.OP(OPCODES.FORLOOP_CONTROL, ref, args);
}
FORIN_INIT(args, ref) {
return this.OP(OPCODES.FORIN_INIT, ref, args);
}
FORIN_CONTROL(args, ref) {
return this.OP(OPCODES.FORIN_CONTROL, ref, args);
}
JUMP(index, ref) {
return this.OP(OPCODES.JUMP, ref, index);
}
JUMPY(index, ref) {
return this.OP(OPCODES.JUMPY, ref, index);
}
JUMPN(index, ref) {
return this.OP(OPCODES.JUMPN, ref, index);
}
JUMPY_NOPOP(index, ref) {
return this.OP(OPCODES.JUMPY_NOPOP, ref, index);
}
JUMPN_NOPOP(index, ref) {
return this.OP(OPCODES.JUMPN_NOPOP, ref, index);
}
STORE_LOCAL(index, ref) {
return this.OP(OPCODES.STORE_LOCAL, ref, index);
}
STORE_VARIABLE(field, ref) {
return this.OP(OPCODES.STORE_VARIABLE, ref, field);
}
CREATE_PROPERTY(ref) {
return this.OP(OPCODES.CREATE_PROPERTY, ref);
}
STORE_PROPERTY(ref) {
return this.OP(OPCODES.STORE_PROPERTY, ref);
}
LOAD_ROUTINE(value, ref) {
return this.OP(OPCODES.LOAD_ROUTINE, ref, value);
}
FUNCTION_CALL(args, ref) {
return this.OP(OPCODES.FUNCTION_CALL, ref, args);
}
FUNCTION_APPLY_VARIABLE(args, ref) {
return this.OP(OPCODES.FUNCTION_APPLY_VARIABLE, ref, args);
}
FUNCTION_APPLY_PROPERTY(args, ref) {
return this.OP(OPCODES.FUNCTION_APPLY_PROPERTY, ref, args);
}
SUPER_CALL(args, ref) {
return this.OP(OPCODES.SUPER_CALL, ref, args);
}
RETURN(ref) {
return this.OP(OPCODES.RETURN, ref);
}
AFTER(ref) {
return this.OP(OPCODES.AFTER, ref);
}
EVERY(ref) {
return this.OP(OPCODES.EVERY, ref);
}
DO(ref) {
return this.OP(OPCODES.DO, ref);
}
SLEEP(ref) {
return this.OP(OPCODES.SLEEP, ref);
}
DELETE(ref) {
return this.OP(OPCODES.DELETE, ref);
}
UNARY_OP(f, ref) {
return this.OP(OPCODES.UNARY_OP, ref, f);
}
BINARY_OP(f, ref) {
return this.OP(OPCODES.BINARY_OP, ref, f);
}
toString() {
var i, j, len, op, ref1, s;
s = "";
ref1 = this.opcodes;
for (i = j = 0, len = ref1.length; j < len; i = ++j) {
op = ref1[i];
s += OPCODES[op];
if (this.arg1[i] != null) {
//if typeof @arg1[i] != "function"
s += ` ${this.arg1[i]}`;
}
s += "\n";
}
return s;
}
exportArg(arg) {
if (arg == null) {
return 0;
} else if (arg instanceof Routine) {
return arg.export();
} else if (typeof arg === "function") {
return arg.name;
} else {
return arg;
}
}
export() {
var args, i, j, ref1, res;
args = [];
for (i = j = 0, ref1 = this.arg1.length - 1; j <= ref1; i = j += 1) {
args[i] = this.exportArg(this.arg1[i]);
}
res = {
num_args: this.num_args,
ops: this.opcodes,
args: args,
import_refs: this.import_refs,
import_values: this.import_values,
import_self: this.import_self,
locals_size: this.locals_size
};
return res;
}
import(src) {
var i, j, ref, ref1, token;
this.num_args = src.num_args;
this.opcodes = src.ops;
this.arg1 = src.args;
this.import_refs = src.import_refs;
this.import_values = src.import_values;
this.import_self = src.import_self;
this.locals_size = src.locals_size;
token = {
line: 0,
column: 0,
start: 0,
length: 0,
index: 0,
tokenizer: {
filename: "filename",
input: ""
}
};
ref = {
expression: {
token: token
},
token: token
};
for (i = j = 0, ref1 = this.opcodes.length - 1; j <= ref1; i = j += 1) {
if (this.opcodes[i] === 100) {
this.arg1[i] = Compiler.predefined_unary_functions[this.arg1[i]];
} else if (this.opcodes[i] === 101) {
this.arg1[i] = Compiler.predefined_binary_functions[this.arg1[i]];
} else if (typeof this.arg1[i] === "object" && !Array.isArray(this.arg1[i])) {
this.arg1[i] = new Routine(0).import(this.arg1[i]);
}
this.ref[i] = ref;
}
return this;
}
};
this.OPCODES_CLASS = class OPCODES_CLASS {
constructor() {
this.table = {};
this.set("TYPE", 1);
this.set("VARIABLE_TYPE", 2);
this.set("PROPERTY_TYPE", 3);
this.set("LOAD_IMPORT", 4);
this.set("LOAD_THIS", 5);
this.set("LOAD_GLOBAL", 6);
this.set("LOAD_VALUE", 10);
this.set("LOAD_LOCAL", 11);
this.set("LOAD_VARIABLE", 12);
this.set("LOAD_LOCAL_OBJECT", 13);
this.set("LOAD_VARIABLE_OBJECT", 14);
this.set("POP", 15);
this.set("LOAD_PROPERTY", 16);
this.set("LOAD_PROPERTY_OBJECT", 17);
this.set("CREATE_OBJECT", 18);
this.set("MAKE_OBJECT", 19);
this.set("CREATE_ARRAY", 20);
this.set("STORE_LOCAL", 21);
this.set("STORE_VARIABLE", 23);
this.set("CREATE_PROPERTY", 24);
this.set("STORE_PROPERTY", 25);
this.set("DELETE", 26);
this.set("UPDATE_CLASS", 27);
this.set("CREATE_CLASS", 28);
this.set("NEW_CALL", 29);
this.set("ADD", 30);
this.set("SUB", 31);
this.set("MUL", 32);
this.set("DIV", 33);
this.set("MODULO", 34);
this.set("BINARY_AND", 35);
this.set("BINARY_OR", 36);
this.set("SHIFT_LEFT", 37);
this.set("SHIFT_RIGHT", 38);
this.set("NEGATE", 39);
this.set("EQ", 40);
this.set("NEQ", 41);
this.set("LT", 42);
this.set("GT", 43);
this.set("LTE", 44);
this.set("GTE", 45);
this.set("NOT", 50);
this.set("LOAD_PROPERTY_ATOP", 68);
this.set("JUMP", 80);
this.set("JUMPY", 81);
this.set("JUMPN", 82);
this.set("JUMPY_NOPOP", 83);
this.set("JUMPN_NOPOP", 84);
this.set("LOAD_ROUTINE", 89);
this.set("FUNCTION_CALL", 90);
this.set("FUNCTION_APPLY_VARIABLE", 91);
this.set("FUNCTION_APPLY_PROPERTY", 92);
this.set("SUPER_CALL", 93);
this.set("RETURN", 94);
this.set("FORLOOP_INIT", 95);
this.set("FORLOOP_CONTROL", 96);
this.set("FORIN_INIT", 97);
this.set("FORIN_CONTROL", 98);
this.set("UNARY_OP", 100);
this.set("BINARY_OP", 101);
this.set("COMPILED", 200);
this.set("AFTER", 110);
this.set("EVERY", 111);
this.set("DO", 112);
this.set("SLEEP", 113);
}
set(op, code) {
this[op] = code;
return this[code] = op;
}
};
this.OPCODES = new this.OPCODES_CLASS;
@@ -0,0 +1,385 @@
this.Runner = class Runner {
constructor(microvm) {
this.microvm = microvm;
}
init() {
this.initialized = true;
this.system = this.microvm.context.global.system;
this.system.preemptive = 1;
this.system.threads = [];
this.main_thread = new Thread(this);
this.threads = [this.main_thread];
this.current_thread = this.main_thread;
this.thread_index = 0;
this.microvm.context.global.print = this.microvm.context.meta.print;
this.microvm.context.global.random = new Random(0);
this.microvm.context.global.Function = {
bind: function(obj) {
var rc;
if (this instanceof Routine) {
rc = this.clone();
rc.object = obj;
return rc;
} else {
return this;
}
}
};
this.microvm.context.global.List = {
sortList: (f) => {
var funk;
if ((f != null) && f instanceof Program.Function) {
funk = function(a, b) {
return f.call(this.microvm.context.global, [a, b], true);
};
} else if ((f != null) && typeof f === "function") {
funk = f;
}
return this.sort(funk);
},
"+": function(a, b, self) {
if (!self) { // not +=, clone array a
a = [...a];
}
if (Array.isArray(b)) {
return a.concat(b);
} else {
a.push(b);
return a;
}
},
"-": function(a, b, self) {
var index;
if (!self) { // not -=, clone array a
a = [...a];
}
index = a.indexOf(b);
if (index >= 0) {
a.splice(index, 1);
}
return a;
}
};
this.microvm.context.global.Object = {};
this.microvm.context.global.String = {
fromCharCode: function(...args) { return String.fromCharCode(...args) },
"+": function(a, b) {
return a + b;
}
};
this.microvm.context.global.Number = {
parse: function(s) {
var res;
res = Number.parseFloat(s);
if (isFinite(res)) {
return res;
} else {
return 0;
}
},
toString: function() {
return this.toString();
}
};
this.fps = 60;
this.fps_max = 60;
this.cpu_load = 0;
this.microvm.context.meta.print("microScript 2.0");
return this.triggers_controls_update = true;
}
run(src, filename, callback) {
var compiler, err, id, j, len, parser, program, ref, result, w;
if (!this.initialized) {
this.init();
}
parser = new Parser(src, filename);
parser.parse();
if (parser.error_info != null) {
err = parser.error_info;
err.type = "compile";
throw err;
}
if (parser.warnings.length > 0) {
ref = parser.warnings;
for (j = 0, len = ref.length; j < len; j++) {
w = ref[j];
id = filename + "-" + w.line + "-" + w.column;
switch (w.type) {
case "assigning_api_variable":
if (this.microvm.context.warnings.assigning_api_variable[id] == null) {
this.microvm.context.warnings.assigning_api_variable[id] = {
file: filename,
line: w.line,
column: w.column,
expression: w.identifier
};
}
break;
case "assignment_as_condition":
if (this.microvm.context.warnings.assignment_as_condition[id] == null) {
this.microvm.context.warnings.assignment_as_condition[id] = {
file: filename,
line: w.line,
column: w.column
};
}
}
}
}
program = parser.program;
compiler = new Compiler(program);
result = null;
compiler.routine.callback = function(res) {
if (callback != null) {
return callback(Program.toString(res));
} else {
return result = res;
}
};
this.main_thread.addCall(compiler.routine);
this.tick();
return result;
}
call(name, args) {
var f, routine;
if (name === "draw" || name === "update" || name === "serverUpdate") {
if (this.microvm.context.global[name] != null) {
this.main_thread.addCall(`${name}()`);
}
return;
}
if (this.microvm.context.global[name] != null) {
if ((args == null) || !args.length) {
return this.main_thread.addCall(`${name}()`);
} else {
routine = this.microvm.context.global[name];
if (routine instanceof Routine) {
f = this.main_thread.processor.routineAsFunction(routine, this.microvm.context);
return f(...args);
} else if (typeof routine === "function") {
return routine(...args);
}
}
} else {
return 0;
}
}
toString(obj) {
return Program.toString(obj);
}
process(thread, time_limit) {
var processor;
processor = thread.processor;
processor.time_limit = time_limit;
this.current_thread = thread;
return processor.run(this.microvm.context);
}
tick() {
var dt, frame_time, i, index, j, k, len, load, margin, processing, processor, ref, ref1, t, time, time_limit, time_out;
if (this.system.fps != null) {
this.fps = this.fps * .9 + this.system.fps * .1;
}
this.fps_max = Math.max(this.fps, this.fps_max);
frame_time = Math.min(16, Math.floor(1000 / this.fps_max));
if (this.fps < 59) {
margin = 10;
} else {
margin = Math.floor(1000 / this.fps * .8);
}
time = Date.now();
time_limit = time + 100; // allow more time to prevent interrupting main_thread in the middle of a draw()
time_out = this.system.preemptive ? time_limit : 2e308;
processor = this.main_thread.processor;
if (!processor.done) {
if (this.main_thread.sleep_until != null) {
if (Date.now() >= this.main_thread.sleep_until) {
delete this.main_thread.sleep_until;
this.process(this.main_thread, time_out);
}
} else {
this.process(this.main_thread, time_out);
}
}
while (processor.done && Date.now() < time_out && this.main_thread.loadNext()) {
this.process(this.main_thread, time_out);
}
time_limit = time + margin; // secondary threads get remaining time
time_out = this.system.preemptive ? time_limit : 2e308;
processing = true;
while (processing) {
processing = false;
ref = this.threads;
for (j = 0, len = ref.length; j < len; j++) {
t = ref[j];
if (t !== this.main_thread) {
if (t.paused || t.terminated) {
continue;
}
processor = t.processor;
if (!processor.done) {
if (t.sleep_until != null) {
if (Date.now() >= t.sleep_until) {
delete t.sleep_until;
this.process(t, time_out);
processing = true;
}
} else {
this.process(t, time_out);
processing = true;
}
} else if (t.start_time != null) {
if (t.repeat) {
while (time >= t.start_time && !(t.paused || t.terminated)) {
if (time >= t.start_time + 150) {
t.start_time = time + t.delay;
} else {
t.start_time += t.delay;
}
processor.load(t.routine);
this.process(t, time_out);
processing = true;
}
} else {
if (time >= t.start_time) {
delete t.start_time;
processor.load(t.routine);
this.process(t, time_out);
processing = true;
}
}
} else {
t.terminated = true;
}
}
}
if (Date.now() > time_limit) {
break;
}
}
for (i = k = ref1 = this.threads.length - 1; k >= 1; i = k += -1) {
t = this.threads[i];
if (t.terminated) {
this.threads.splice(i, 1);
index = this.system.threads.indexOf(t.interface);
if (index >= 0) {
this.system.threads.splice(index, 1);
}
}
}
t = Date.now() - time;
dt = time_limit - time;
load = t / dt * 100;
this.cpu_load = this.cpu_load * .9 + load * .1;
this.system.cpu_load = Math.min(100, Math.round(this.cpu_load));
}
createThread(routine, delay, repeat) {
var i, j, ref, t;
t = new Thread(this);
t.routine = routine;
this.threads.push(t);
t.start_time = Date.now() + delay - 1000 / this.fps;
if (repeat) {
t.repeat = repeat;
t.delay = delay;
}
this.system.threads.push(t.interface);
for (i = j = 0, ref = routine.import_values.length - 1; j <= ref; i = j += 1) {
if (routine.import_values[i] === routine) {
routine.import_values[i] = t.interface;
}
}
return t.interface;
}
sleep(value) {
if (this.current_thread != null) {
return this.current_thread.sleep_until = Date.now() + Math.max(0, value);
}
}
};
this.Thread = class Thread {
constructor(runner) {
this.runner = runner;
this.loop = false;
this.processor = new Processor(this.runner);
this.paused = false;
this.terminated = false;
this.next_calls = [];
this.interface = {
pause: () => {
return this.pause();
},
resume: () => {
return this.resume();
},
stop: () => {
return this.stop();
},
status: "running"
};
}
addCall(call) {
if (this.next_calls.indexOf(call) < 0) {
return this.next_calls.push(call);
}
}
loadNext() {
var compiler, f, parser, program;
if (this.next_calls.length > 0) {
f = this.next_calls.splice(0, 1)[0];
if (f instanceof Routine) {
this.processor.load(f);
} else {
parser = new Parser(f, "");
parser.parse();
program = parser.program;
compiler = new Compiler(program);
this.processor.load(compiler.routine);
if ((f === "update()" || f === "serverUpdate()") && (this.runner.updateControls != null)) {
this.runner.updateControls();
}
}
return true;
} else {
return false;
}
}
pause() {
if (this.interface.status === "running") {
this.interface.status = "paused";
this.paused = true;
return 1;
} else {
return 0;
}
}
resume() {
if (this.interface.status === "paused") {
this.interface.status = "running";
this.paused = false;
return 1;
} else {
return 0;
}
}
stop() {
this.interface.status = "stopped";
this.terminated = true;
return 1;
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

@@ -0,0 +1,201 @@
this.Token = class Token {
constructor(tokenizer, type, value, string_value) {
this.tokenizer = tokenizer;
this.type = type;
this.value = value;
this.string_value = string_value;
this.line = this.tokenizer.line;
this.column = this.tokenizer.column;
this.start = this.tokenizer.token_start;
this.length = this.tokenizer.index - this.start;
this.index = this.tokenizer.index;
if (this.type === Token.TYPE_IDENTIFIER && Token.predefined.hasOwnProperty(this.value)) {
this.type = Token.predefined[this.value];
this.reserved_keyword = true;
}
this.is_binary_operator = (this.type >= 30 && this.type <= 39) || (this.type >= 200 && this.type <= 201) || (this.type >= 2 && this.type <= 7);
}
toString() {
return this.value + " : " + this.type;
}
};
this.Token.TYPE_EQUALS = 1;
this.Token.TYPE_DOUBLE_EQUALS = 2;
this.Token.TYPE_GREATER = 3;
this.Token.TYPE_GREATER_OR_EQUALS = 4;
this.Token.TYPE_LOWER = 5;
this.Token.TYPE_LOWER_OR_EQUALS = 6;
this.Token.TYPE_UNEQUALS = 7;
this.Token.TYPE_IDENTIFIER = 10;
this.Token.TYPE_NUMBER = 11;
this.Token.TYPE_STRING = 12;
this.Token.TYPE_OPEN_BRACE = 20;
this.Token.TYPE_CLOSED_BRACE = 21;
// @Token.TYPE_OPEN_CURLY_BRACE = 22
// @Token.TYPE_CLOSED_CURLY_BRACE = 23
this.Token.TYPE_OPEN_BRACKET = 24;
this.Token.TYPE_CLOSED_BRACKET = 25;
this.Token.TYPE_COMMA = 26;
this.Token.TYPE_DOT = 27;
this.Token.TYPE_PLUS = 30;
this.Token.TYPE_MINUS = 31;
this.Token.TYPE_MULTIPLY = 32;
this.Token.TYPE_DIVIDE = 33;
this.Token.TYPE_POWER = 34;
this.Token.TYPE_MODULO = 35;
this.Token.TYPE_BINARY_AND = 36;
this.Token.TYPE_BINARY_OR = 37;
this.Token.TYPE_SHIFT_LEFT = 38;
this.Token.TYPE_SHIFT_RIGHT = 39;
this.Token.TYPE_PLUS_EQUALS = 40;
this.Token.TYPE_MINUS_EQUALS = 41;
this.Token.TYPE_MULTIPLY_EQUALS = 42;
this.Token.TYPE_DIVIDE_EQUALS = 43;
this.Token.TYPE_MODULO_EQUALS = 44;
this.Token.TYPE_AND_EQUALS = 45;
this.Token.TYPE_OR_EQUALS = 46;
this.Token.TYPE_RETURN = 50;
this.Token.TYPE_BREAK = 51;
this.Token.TYPE_CONTINUE = 52;
this.Token.TYPE_FUNCTION = 60;
this.Token.TYPE_AFTER = 61;
this.Token.TYPE_EVERY = 62;
this.Token.TYPE_DO = 63;
this.Token.TYPE_SLEEP = 64;
this.Token.TYPE_LOCAL = 70;
this.Token.TYPE_OBJECT = 80;
this.Token.TYPE_CLASS = 90;
this.Token.TYPE_EXTENDS = 91;
this.Token.TYPE_NEW = 92;
this.Token.TYPE_FOR = 100;
this.Token.TYPE_TO = 101;
this.Token.TYPE_BY = 102;
this.Token.TYPE_IN = 103;
this.Token.TYPE_WHILE = 104;
this.Token.TYPE_IF = 105;
this.Token.TYPE_THEN = 106;
this.Token.TYPE_ELSE = 107;
this.Token.TYPE_ELSIF = 108;
this.Token.TYPE_END = 120;
this.Token.TYPE_AND = 200;
this.Token.TYPE_OR = 201;
this.Token.TYPE_NOT = 202;
this.Token.TYPE_ERROR = 404;
this.Token.predefined = {};
this.Token.predefined["return"] = this.Token.TYPE_RETURN;
this.Token.predefined["break"] = this.Token.TYPE_BREAK;
this.Token.predefined["continue"] = this.Token.TYPE_CONTINUE;
this.Token.predefined["function"] = this.Token.TYPE_FUNCTION;
this.Token.predefined["for"] = this.Token.TYPE_FOR;
this.Token.predefined["to"] = this.Token.TYPE_TO;
this.Token.predefined["by"] = this.Token.TYPE_BY;
this.Token.predefined["in"] = this.Token.TYPE_IN;
this.Token.predefined["while"] = this.Token.TYPE_WHILE;
this.Token.predefined["if"] = this.Token.TYPE_IF;
this.Token.predefined["then"] = this.Token.TYPE_THEN;
this.Token.predefined["else"] = this.Token.TYPE_ELSE;
this.Token.predefined["elsif"] = this.Token.TYPE_ELSIF;
this.Token.predefined["end"] = this.Token.TYPE_END;
this.Token.predefined["object"] = this.Token.TYPE_OBJECT;
this.Token.predefined["class"] = this.Token.TYPE_CLASS;
this.Token.predefined["extends"] = this.Token.TYPE_EXTENDS;
this.Token.predefined["new"] = this.Token.TYPE_NEW;
this.Token.predefined["and"] = this.Token.TYPE_AND;
this.Token.predefined["or"] = this.Token.TYPE_OR;
this.Token.predefined["not"] = this.Token.TYPE_NOT;
this.Token.predefined["after"] = this.Token.TYPE_AFTER;
this.Token.predefined["every"] = this.Token.TYPE_EVERY;
this.Token.predefined["do"] = this.Token.TYPE_DO;
this.Token.predefined["sleep"] = this.Token.TYPE_SLEEP;
this.Token.predefined["delete"] = this.Token.TYPE_DELETE;
this.Token.predefined["local"] = this.Token.TYPE_LOCAL;
@@ -0,0 +1,343 @@
this.Tokenizer = (function() {
function Tokenizer(input, filename) {
this.input = input;
this.filename = filename;
this.index = 0;
this.line = 1;
this.column = 0;
this.last_column = 0;
this.buffer = [];
this.chars = {};
this.chars["("] = Token.TYPE_OPEN_BRACE;
this.chars[")"] = Token.TYPE_CLOSED_BRACE;
this.chars["["] = Token.TYPE_OPEN_BRACKET;
this.chars["]"] = Token.TYPE_CLOSED_BRACKET;
this.chars["{"] = Token.TYPE_OPEN_CURLY_BRACE;
this.chars["}"] = Token.TYPE_CLOSED_CURLY_BRACE;
this.chars["^"] = Token.TYPE_POWER;
this.chars[","] = Token.TYPE_COMMA;
this.chars["."] = Token.TYPE_DOT;
this.doubles = {};
this.doubles[">"] = [Token.TYPE_GREATER, Token.TYPE_GREATER_OR_EQUALS];
this.doubles["<"] = [Token.TYPE_LOWER, Token.TYPE_LOWER_OR_EQUALS];
this.doubles["="] = [Token.TYPE_EQUALS, Token.TYPE_DOUBLE_EQUALS];
this.doubles["+"] = [Token.TYPE_PLUS, Token.TYPE_PLUS_EQUALS];
this.doubles["-"] = [Token.TYPE_MINUS, Token.TYPE_MINUS_EQUALS];
this.doubles["*"] = [Token.TYPE_MULTIPLY, Token.TYPE_MULTIPLY_EQUALS];
this.doubles["/"] = [Token.TYPE_DIVIDE, Token.TYPE_DIVIDE_EQUALS];
this.doubles["%"] = [Token.TYPE_MODULO, Token.TYPE_MODULO_EQUALS];
this.doubles["&"] = [Token.TYPE_BINARY_AND, Token.TYPE_AND_EQUALS];
this.doubles["|"] = [Token.TYPE_BINARY_OR, Token.TYPE_OR_EQUALS];
this.shifts = {
"<": Token.TYPE_SHIFT_LEFT,
">": Token.TYPE_SHIFT_RIGHT
};
this.letter_regex = RegExp(/^\p{L}/, 'u');
}
Tokenizer.prototype.pushBack = function(token) {
return this.buffer.splice(0, 0, token);
};
Tokenizer.prototype.finished = function() {
return this.index >= this.input.length && this.buffer.length === 0;
};
Tokenizer.prototype.nextChar = function(ignore_comments) {
var c, endseq;
if (ignore_comments == null) {
ignore_comments = false;
}
c = this.input.charAt(this.index++);
if (c === "\n") {
this.line += 1;
this.last_column = this.column;
this.column = 0;
} else if (c === "/" && !ignore_comments) {
if (this.input.charAt(this.index) === "/") {
while (true) {
c = this.input.charAt(this.index++);
if (c === "\n" || this.index >= this.input.length) {
break;
}
}
this.line += 1;
this.last_column = this.column;
this.column = 0;
return this.nextChar();
} else if (this.input.charAt(this.index) === "*") {
endseq = 0;
while (true) {
c = this.input.charAt(this.index++);
if (c === "\n") {
this.line += 1;
this.last_column = this.column;
this.column = 0;
endseq = 0;
} else if (c === "*") {
endseq = 1;
} else if (c === "/" && endseq === 1) {
break;
} else {
endseq = 0;
}
if (this.index >= this.input.length) {
break;
}
}
return this.nextChar();
}
} else {
this.column += 1;
}
return c;
};
Tokenizer.prototype.rewind = function() {
this.index -= 1;
this.column -= 1;
if (this.input.charAt(this.index) === "\n") {
this.line -= 1;
return this.column = this.last_column;
}
};
Tokenizer.prototype.next = function() {
var c, code;
if (this.buffer.length > 0) {
return this.buffer.splice(0, 1)[0];
}
while (true) {
if (this.index >= this.input.length) {
return null;
}
c = this.nextChar();
code = c.charCodeAt(0);
if (code > 32 && code !== 160) {
break;
}
}
this.token_start = this.index - 1;
if (this.doubles[c] != null) {
return this.parseDouble(c, this.doubles[c]);
}
if (this.chars[c] != null) {
return new Token(this, this.chars[c], c);
}
if (c === "!") {
return this.parseUnequals(c);
} else if (code >= 48 && code <= 57) {
return this.parseNumber(c);
} else if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122) || code === 95 || this.letter_regex.test(c)) {
return this.parseIdentifier(c);
} else if (c === '"') {
return this.parseString(c, '"');
} else if (c === "'") {
return this.parseString(c, "'");
} else {
return this.error("Syntax Error");
}
};
Tokenizer.prototype.changeNumberToIdentifier = function() {
var i, j, ref, results, token, v;
token = this.next();
if ((token != null) && token.type === Token.TYPE_NUMBER) {
v = token.string_value.split(".");
results = [];
for (i = j = ref = v.length - 1; j >= 0; i = j += -1) {
if (v[i].length > 0) {
this.pushBack(new Token(this, Token.TYPE_IDENTIFIER, v[i]));
}
if (i > 0) {
results.push(this.pushBack(new Token(this, Token.TYPE_DOT, ".")));
} else {
results.push(void 0);
}
}
return results;
} else if ((token != null) && token.type === Token.TYPE_STRING) {
return this.pushBack(new Token(this, Token.TYPE_IDENTIFIER, token.value));
} else {
return this.pushBack(token);
}
};
Tokenizer.prototype.parseDouble = function(c, d) {
if ((this.shifts[c] != null) && this.index < this.input.length && this.input.charAt(this.index) === c) {
this.nextChar();
return new Token(this, this.shifts[c], c + c);
} else if (this.index < this.input.length && this.input.charAt(this.index) === "=") {
this.nextChar();
return new Token(this, d[1], c + "=");
} else {
return new Token(this, d[0], c);
}
};
Tokenizer.prototype.parseEquals = function(c) {
if (this.index < this.input.length && this.input.charAt(this.index) === "=") {
this.nextChar();
return new Token(this, Token.TYPE_DOUBLE_EQUALS, "==");
} else {
return new Token(this, Token.TYPE_EQUALS, "=");
}
};
Tokenizer.prototype.parseGreater = function(c) {
if (this.index < this.input.length && this.input.charAt(this.index) === "=") {
this.nextChar();
return new Token(this, Token.TYPE_GREATER_OR_EQUALS, ">=");
} else {
return new Token(this, Token.TYPE_GREATER_OR_EQUALS, ">");
}
};
Tokenizer.prototype.parseLower = function(c) {
if (this.index < this.input.length && this.input.charAt(this.index) === "=") {
this.nextChar();
return new Token(this, Token.TYPE_LOWER_OR_EQUALS, "<=");
} else {
return new Token(this, Token.TYPE_LOWER, "<");
}
};
Tokenizer.prototype.parseUnequals = function(c) {
if (this.index < this.input.length && this.input.charAt(this.index) === "=") {
this.nextChar();
return new Token(this, Token.TYPE_UNEQUALS, "!=");
} else {
return this.error("Expected inequality !=");
}
};
Tokenizer.prototype.parseIdentifier = function(s) {
var c, code;
while (true) {
if (this.index >= this.input.length) {
return new Token(this, Token.TYPE_IDENTIFIER, s);
}
c = this.nextChar();
code = c.charCodeAt(0);
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122) || code === 95 || (code >= 48 && code <= 57) || this.letter_regex.test(c)) {
s += c;
} else {
this.rewind();
return new Token(this, Token.TYPE_IDENTIFIER, s);
}
}
};
Tokenizer.prototype.parseNumber = function(s) {
var c, code, exp, pointed;
pointed = false;
exp = false;
while (true) {
if (this.index >= this.input.length) {
return new Token(this, Token.TYPE_NUMBER, Number.parseFloat(s), s);
}
c = this.nextChar();
code = c.charCodeAt(0);
if (c === "." && !pointed && !exp) {
pointed = true;
s += c;
} else if (code >= 48 && code <= 57) {
s += c;
} else if ((c === "e" || c === "E") && !exp && this.index < this.input.length) {
exp = true;
s += c;
c = this.nextChar();
if (c === "+" || c === "-") {
s += c;
} else {
this.rewind();
}
} else if ((c === "x" || c === "X") && s === "0") {
return this.parseHexNumber("0x");
} else {
this.rewind();
return new Token(this, Token.TYPE_NUMBER, Number.parseFloat(s), s);
}
}
};
Tokenizer.prototype.parseHexNumber = function(s) {
var c;
while (true) {
if (this.index >= this.input.length) {
return new Token(this, Token.TYPE_NUMBER, Number.parseInt(s), s);
}
c = this.nextChar();
if (/[a-fA-F0-9]/.test(c)) {
s += c;
} else {
this.rewind();
return new Token(this, Token.TYPE_NUMBER, Number.parseInt(s), s);
}
}
};
Tokenizer.prototype.parseString = function(s, close) {
var c, code, count_close, n;
if (close == null) {
close = '"';
}
if (close === '"') {
if (this.input.charAt(this.index) === '"' && this.input.charAt(this.index + 1) === '"' && this.input.charAt(this.index + 2) !== '"') {
close = '"""';
this.nextChar(true);
this.nextChar(true);
}
}
count_close = 0;
while (true) {
if (this.index >= this.input.length) {
return this.error("Unclosed string value");
}
c = this.nextChar(true);
code = c.charCodeAt(0);
if (c === "\\") {
n = this.nextChar(true);
switch (n) {
case "n":
s += "\n";
break;
case "\\":
s += "\\";
break;
case close:
s += close;
break;
default:
s += "\\" + n;
}
} else if (c === close) {
n = this.nextChar(true);
if (n === close) {
s += c;
} else {
this.rewind();
s += c;
return new Token(this, Token.TYPE_STRING, s.substring(1, s.length - 1));
}
} else {
if (close === '"""' && c === '"') {
count_close += 1;
if (count_close === 3) {
return new Token(this, Token.TYPE_STRING, s.substring(1, s.length - 2));
}
} else {
count_close = 0;
}
s += c;
}
}
};
Tokenizer.prototype.error = function(s) {
throw s;
};
return Tokenizer;
})();
@@ -0,0 +1,244 @@
var Transpiler;
Transpiler = (function() {
function Transpiler() {}
Transpiler.prototype.transpile = function(r) {
var i, j, l, op, ref, results;
results = [];
for (i = l = 0, ref = r.opcodes.length - 1; l <= ref; i = l += 1) {
op = OPCODES[r.opcodes[i]];
if (this.transpilable(op, r.arg1[i])) {
j = i + 1;
while (j < r.opcodes.length && r.removeable(j) && this.transpilable(OPCODES[r.opcodes[j]], r.arg1[j])) {
j += 1;
}
j -= 1;
if (j - i >= 2) {
results.push(this.transpileSegment(r, i, j));
} else {
results.push(void 0);
}
} else {
results.push(void 0);
}
}
return results;
};
Transpiler.prototype.transpileSegment = function(r, i, j) {
var comp, err, index, k, l, m, ref, ref1, ref2, ref3, s;
this.vcount = 0;
this.stack = new Stack();
this.locals = {};
this.variables = {};
s = "f = function(stack,stack_index,locals,locals_offset,object,global) {\n";
for (k = l = ref = i, ref1 = j; l <= ref1; k = l += 1) {
console.info(OPCODES[r.opcodes[k]] + " " + r.arg1[k]);
comp = this[OPCODES[r.opcodes[k]]](r.arg1[k]);
if (comp) {
s += comp + "\n";
}
}
for (index in this.stack.touched) {
if (this.stack.touched[index]) {
if (index < 0) {
s += "stack[stack_index-" + (Math.abs(index)) + "] = " + this.stack.stack[index] + " ;\n";
} else if (index > 0) {
s += "stack[stack_index+" + index + "] = " + this.stack.stack[index] + " ;\n";
} else {
s += "stack[stack_index] = " + this.stack.stack[index] + " ;\n";
}
}
}
if (this.stack.index < 0) {
s += "stack_index -= " + (Math.abs(this.stack.index)) + " ;\n";
} else if (this.stack.index > 0) {
s += "stack_index += " + this.stack.index + " ;\n";
}
s += "return stack_index ;\n}";
console.info(s);
try {
eval(s);
} catch (error) {
err = error;
console.error(s);
console.error(err);
}
r.opcodes[i] = 200;
r.arg1[i] = f;
for (k = m = ref2 = i + 1, ref3 = j; m <= ref3; k = m += 1) {
r.remove(i + 1);
}
};
Transpiler.prototype.createVariable = function() {
return "v" + (this.vcount++);
};
Transpiler.prototype.transpilable = function(op, arg) {
var ref;
if (op === "LOAD_VALUE") {
return (ref = typeof arg) === "string" || ref === "number";
} else {
return this[op] != null;
}
};
Transpiler.prototype.LOAD_VALUE = function(arg) {
if (typeof arg === "string") {
this.stack.push(" \"" + (arg.replace(/"/g, "\\\"")) + "\" ");
} else if (typeof arg === "number") {
this.stack.push(arg + "");
}
return "";
};
Transpiler.prototype.LOAD_LOCAL = function(arg) {
var v;
v = this.createVariable();
this.stack.push(v);
return "let " + v + " = locals[locals_offset+" + arg + "] ; // LOAD_LOCAL";
};
Transpiler.prototype.LOAD_LOCAL_OBJECT = function(arg) {
var res, v;
if (this.locals[arg] != null) {
v = this.locals[arg];
this.stack.push(v);
return "if (typeof " + v + " != \"object\") { " + v + " = locals[locals_offset+" + arg + "] = {} } ;";
} else {
v = this.createVariable();
res = "let " + v + " = locals[locals_offset+" + arg + "] ;\nif (typeof " + v + " != \"object\") { " + v + " = locals[locals_offset+" + arg + "] = {} } ;";
this.stack.push(v);
this.locals[arg] = v;
return res;
}
};
Transpiler.prototype.STORE_LOCAL = function(arg) {
var v;
v = this.stack.get();
return "locals[locals_offset+" + arg + "] = " + v + " ; // STORE_LOCAL";
};
Transpiler.prototype.POP = function() {
this.stack.pop();
return "";
};
Transpiler.prototype.CREATE_PROPERTY = function(arg) {
var res;
res = (this.stack.get(-2)) + "[" + (this.stack.get(-1)) + "] = " + (this.stack.get()) + " ;";
this.stack.pop();
this.stack.pop();
return res;
};
Transpiler.prototype.LOAD_PROPERTY = function(arg) {
var res, v;
v = this.createVariable();
res = "let " + v + " = " + (this.stack.get(-1)) + "[" + (this.stack.get()) + "] ; // LOAD_PROPERTY\nif (" + v + " == null) { " + v + " = 0 ; }";
this.stack.pop();
this.stack.pop();
this.stack.push(v);
return res;
};
Transpiler.prototype.LOAD_PROPERTY_ATOP = function(arg) {
var res, v;
v = this.createVariable();
res = "let " + v + " = " + (this.stack.get(-1)) + "[" + (this.stack.get()) + "] ; // LOAD_PROPERTY_ATOP\nif (" + v + " == null) { " + v + " = 0 ; }";
this.stack.push(v);
return res;
};
Transpiler.prototype.NEW_OBJECT = function() {
var v;
v = this.createVariable();
this.stack.push(v);
return "let " + v + " = {} ;";
};
Transpiler.prototype.NEW_ARRAY = function() {
var v;
v = this.createVariable();
this.stack.push(v);
return "let " + v + " = [] ;";
};
Transpiler.prototype.MAKE_OBJECT = function() {
var res, v;
v = this.createVariable();
res = "let " + v + " = " + (this.stack.get()) + " ;\nif (typeof " + v + " != \"object\") " + v + " = {} ; ";
this.stack.pop();
this.stack.push(v);
return res;
};
Transpiler.prototype.STORE_VARIABLE = function(arg) {
if (this.variables[arg] != null) {
return this.variables[arg] + " = object[\"" + arg + "\"] = " + (this.stack.get()) + " ; // STORE_VARIABLE";
} else {
return "object[\"" + arg + "\"] = " + (this.stack.get()) + " ; // STORE_VARIABLE";
}
};
Transpiler.prototype.STORE_PROPERTY = function(arg) {
var res, v;
v = this.createVariable();
res = "let " + v + " = " + (this.stack.get(-2)) + "[" + (this.stack.get(-1)) + "] = " + (this.stack.get(0)) + " ; // STORE_PROPERTY";
this.stack.pop();
this.stack.pop();
this.stack.pop();
this.stack.push(v);
return res;
};
return Transpiler;
})();
this.Stack = (function() {
function Stack() {
this.stack = ["stack[stack_index]"];
this.index = 0;
this.touched = {};
}
Stack.prototype.push = function(value) {
this.stack[++this.index] = value;
return this.touched[this.index] = true;
};
Stack.prototype.pop = function() {
var res;
if (this.index >= 0) {
res = this.stack.splice(this.index, 1)[0];
} else if (this.stack[this.index] != null) {
res = this.stack[this.index];
} else {
res = "stack[stack_index-" + this.index + "]";
}
this.index -= 1;
return res;
};
Stack.prototype.get = function(index) {
var i;
if (index == null) {
index = 0;
}
i = this.index + index;
if (i >= 0) {
return this.stack[i];
} else if (this.stack[i] != null) {
return this.stack[i];
} else {
return "stack[stack_index-" + (-i) + "]";
}
};
return Stack;
})();
+7
View File
@@ -11,7 +11,14 @@
<head>
<a href="/WebGames-master/WebGames-master/games/cap/index.html">new test</a>
<a href="/WebGames-master/WebGames-master/games/Gladihoppers-gh-pages/index.html">Gladihoppers-gh</a>
<a href="/WebGames-master/WebGames-master/games/microbox/index.html">microbox</a>
<p>this wont look good because its beta testers eyes only</p>
<p>tell us wen to add the to the full vr</p>
<body><!-- begin wwww.htmlcommentbox.com -->
<div id="HCB_comment_box"><a href="http://www.htmlcommentbox.com">Widget</a> is loading comments...</div>
<link rel="stylesheet" type="text/css" href="https://www.htmlcommentbox.com/static/skins/bootstrap/twitter-bootstrap.css?v=0" />
<script type="text/javascript" id="hcb"> /*<!--*/ if(!window.hcb_user){hcb_user={};} (function(){var s=document.createElement("script"), l=hcb_user.PAGE || (""+window.location).replace(/'/g,"%27"), h="https://www.htmlcommentbox.com";s.setAttribute("type","text/javascript");s.setAttribute("src", h+"/jread?page="+encodeURIComponent(l).replace("+","%2B")+"&mod=%241%24wq1rdBcg%24piEQg.u8ZJ10jZd4Ns2cl%2F"+"&opts=16798&num=10&ts=1736864483796");if (typeof s!="undefined") document.getElementsByTagName("head")[0].appendChild(s);})(); /*-->*/ </script>
<!-- end www.htmlcommentbox.com --></body>
</head>
</html>