Skip to content

Instantly share code, notes, and snippets.

@ConorOBrien-Foxx
Created July 18, 2016 02:35
Show Gist options
  • Save ConorOBrien-Foxx/7210642c223d9442c6e845db74609d1c to your computer and use it in GitHub Desktop.
Save ConorOBrien-Foxx/7210642c223d9442c6e845db74609d1c to your computer and use it in GitHub Desktop.
TI-COMPLEX
// converts source to Cemetech-convertable text
// https://www.cemetech.net/sc/
const WORD = /[A-Za-z_$][A-Za-z_$0-9]*/;
// parses a line
const parse = (str) => {
// remove text from semicolon to end, if present
str = str.trim();
let flagStr = false;
for(let i = 0; i < str.length; i++){
if(str[i] === '"'){
flagStr = true;
continue;
}
if(str[i] === ";"){
str = str.slice(0, i);
break;
}
}
// grab initial word
let i = 0;
let keyword = "";
while(WORD.test(str[i]) && str[i]){
keyword += str[i++];
}
i++;
if(i >= str.length) return [keyword];
// get arguments
let args = [];
while(i < str.length){
let cur = "";
if(str[i] === '"'){
while(str[++i] !== '"' && str[i]){
cur += str[i];
}
args.push('"' + cur + str[i++]);
continue;
}
while(/\w/.test(str[i]) && str[i]){
cur += str[i++];
}
args.push(cur);
if(str[i] !== " " && str[i]) args.push(str[i]);
i++;
}
return [keyword, ...args.filter(x => x)];
}
class Address {
constructor(name, ref, value){
this.name = name;
this.ref = ref;
this.value = value;
}
}
const keywords = new Set(["num", "list", "string", "STDIN", "@"]);
const execLine = (line, manager, type) => {
let [cmd, ...params] = Array.isArray(line) ? line : parse(line);
switch(cmd){
case "set": {
let name = params.shift();
if(params[0] === "=") params.shift();
manager.comp += manager.retrieve(params).join("") + "->" + manager.retrieve([name]) + "\n";
} break;
case "list": {
let name = params.shift();
if(params[0] === "=") params.shift();
let vr = manager.alloc.assign(name, manager.retrieve(params).join(""), "list");
manager.comp += vr.value + "->" + vr.ref + "\n";
} break;
case "num":
case "string": {
let name = params.shift();
if(params[0] === "=") params.shift();
let vr;
if(keywords.has(params[0]))
vr = manager.alloc.assign(name, execLine(params, manager, cmd), cmd);
else
vr = manager.alloc.assign(name, params[0], cmd);
manager.comp += vr.value + "->" + vr.ref + "\n";
} break;
case "STDIN": {
let msg = params[0] || '""';
manager.comp += `Prompt ${msg},${type === "num" ? "A" : "Str1"}\n`;
return `A`;
} break;
case "@": {
return manager.retrieve(params).join("");
} break;
case "clear": {
manager.comp += "ClrHome\n";
} break;
case "erase": {
manager.comp += "ClrDraw\n";
} break;
case "while": {
manager.comp += "While " + manager.retrieve(params).join("") + "\n";
} break;
case "end": {
manager.comp += "End\n";
} break;
}
}
const compile = (code) => {
const alloc = new Map();
alloc.syms_n = "EFGHIJKLMNOPQRSTUVWXYZ";
alloc.syms_s = ["Str3", "Str4", "Str5", "Str6", "Str7", "Str8"];
alloc.syms_l = ["L1", "L2", "L3", "L4", "L5", "L6"];
alloc.ind_n = 0;
alloc.ind_s = 0;
alloc.ind_l = 0;
alloc.assign = (name, value, type) =>
alloc.set(
alloc["syms_" + type[0]][alloc["ind_" + type[0]]],
new Address(
name,
alloc["syms_" + type[0]][alloc["ind_" + type[0]]],
value
)
).get(alloc["syms_" + type[0]][alloc["ind_" + type[0]]++]);
alloc.retrieve = (name) => {
let flt = [...alloc.values()].filter(e => e.name === name);
if(flt.length) return flt[0].ref;
return false;
}
alloc.assign("pi", "pi", "number");
const manager = {
alloc: alloc,
comp: "",
retrieve: (l) => l.map(e => alloc.retrieve(e) || e)
};
let lines = code.split("\n");
for(let line of lines){
execLine(line, manager);
}
return manager.comp;
}
// console.log(parse("num[] asdf = {2, 3, 4}"));
console.log(compile(`
num cnt = 0
while cnt <= 5
set cnt = cnt + 1
end
`.trim()));
/*
num first = STDIN ; works!
num second = STDIN "B="
num sum = @first + second
string str = "asdf"
transpiles to
Prompt "",A
A->F
Prompt "B=",A
A->G
F+G->H
"asdf"->Str3
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment