Created
July 18, 2016 02:35
-
-
Save ConorOBrien-Foxx/7210642c223d9442c6e845db74609d1c to your computer and use it in GitHub Desktop.
TI-COMPLEX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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