Last active
November 11, 2017 23:52
-
-
Save PanJarda/18d0adeb525c989d86a18ad40e58d499 to your computer and use it in GitHub Desktop.
Toy - concatenative, functional, stack-based, truly postfix language.
This file contains hidden or 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
const readline = require('readline'); | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}); | |
let stack = []; | |
let consts = { | |
swapd: '[[swap] dip]', | |
popd: '[[pop] dip]', | |
dupd: '[[dup] dip]' | |
}; | |
const eval = (word) => { | |
switch (word) { | |
case "dup": | |
stack.push(stack[stack.length-1]); | |
break; | |
case "swap": | |
var tmp = stack.pop(); | |
var tmp2 = stack.pop(); | |
stack.push(tmp); | |
stack.push(tmp2); | |
break; | |
case "dip": | |
let prog = stack.pop(); | |
tmp = stack.pop(); | |
stack.push(prog); | |
eval("."); | |
stack.push(tmp); | |
break; | |
case "p": | |
case "print": | |
console.log(stack[stack.length-1]); | |
break; | |
case "pop": | |
stack.pop(); | |
break; | |
case "+": | |
stack.push(parseFloat(stack.pop()) + parseFloat(stack.pop())); | |
break; | |
case "-": | |
stack.push(parseFloat(stack.pop()) - parseFloat(stack.pop())); | |
break; | |
case "*": | |
stack.push(parseFloat(stack.pop()) * parseFloat(stack.pop())); | |
break; | |
case "sqrt": | |
stack.push(Math.sqrt(parseFloat(stack.pop()))); | |
break; | |
case "/": | |
stack.push(parseFloat(stack.pop()) / parseFloat(stack.pop())); | |
break; | |
case ">": | |
stack.push(parseFloat(stack.pop()) > parseFloat(stack.pop())); | |
break; | |
case ">=": | |
stack.push(parseFloat(stack.pop()) > parseFloat(stack.pop())); | |
break; | |
case "<": | |
stack.push(parseFloat(stack.pop()) < parseFloat(stack.pop())); | |
break; | |
case "<=": | |
stack.push(parseFloat(stack.pop()) < parseFloat(stack.pop())); | |
break; | |
case "!=": | |
stack.push(parseFloat(stack.pop()) != parseFloat(stack.pop())); | |
break; | |
case "==": | |
stack.push(parseFloat(stack.pop()) == parseFloat(stack.pop())); | |
break; | |
case "?": | |
var predicate = stack.pop(); | |
(predicate != '0' && predicate != 'false') ? eval(".") : stack.pop() && eval("."); | |
break; | |
case "q": | |
case "quit": | |
process.exit(); | |
break; | |
case "c": | |
case "clear": | |
stack = []; | |
break; | |
case ".": | |
let item = stack.pop(); | |
let lambda = item.match(/^\[(.*)\]$/); | |
if (lambda) { | |
lambda[1].split(/\s+(?=(?:[^\'"\[\]]*[\'"\[][^\'"\[\]]*[\'"\]])*[^\'"\[\]]*$)/).forEach(word=>eval(word)) | |
} else { | |
stack.push(item); | |
} | |
break; | |
case ":": | |
consts[stack.pop()] = stack.pop(); | |
break; | |
case "f": | |
case "dump": | |
stack.forEach(a => console.log(a)); | |
break; | |
case "head": | |
stack.push(stack.pop().match(/^\[([^\[\]]*)\]$/)[1].split(/\s+(?=(?:[^\'"\[\]]*[\'"\[][^\'"\[\]]*[\'"\]])*[^\'"\[\]]*$)/)[0]); | |
break; | |
case "tail": | |
let content = stack.pop().match(/^\[([^\[\]]*)\]$/)[1].split(/\s+(?=(?:[^\'"\[\]]*[\'"\[][^\'"\[\]]*[\'"\]])*[^\'"\[\]]*$)/); | |
content.shift(); | |
stack.push("[" + content.join(" ") + "]"); | |
break; | |
case "cons": | |
stack.push("[" + stack.pop() + " " + stack.pop() + "]"); | |
break; | |
case "map": | |
let array = stack.pop().match(/^\[([^\[\]]*)\]$/)[1].split(/\s+(?=(?:[^\'"\[\]]*[\'"\[][^\'"\[\]]*[\'"\]])*[^\'"\[\]]*$)/); | |
let fn = stack.pop(); | |
stack.push("[" + array.map(item => { | |
stack.push(item); | |
stack.push(fn); | |
eval("."); | |
return stack.pop();}).join(" ") +"]"); | |
break; | |
case "concat": // sezere dve makra a spoji je do jednoho | |
stack.push("[" + stack.pop().match(/\[(.*)\]/)[1] + " " + stack.pop().match(/\[(.*)\]/)[1] + "]"); | |
break; | |
case "quote": | |
stack.push("[" + stack.pop() + "]"); | |
break; | |
default: | |
var isquoted; | |
if (isquoted = word.toString().match(/^\[(.*)\]/)) { | |
stack.push(word); | |
} else { | |
if (consts[word]) { | |
eval(consts[word]); eval("."); | |
} else { | |
stack.push(word); | |
} | |
} | |
} | |
}; | |
rl.on('line', (input) => { | |
let wordlist = input.split(/\s+(?=(?:[^\'"\[\]]*[\'"\[][^\'"\[\]]*[\'"\]])*[^\'"\[\]]*$)/); | |
wordlist.forEach(word => eval(word)); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment