Last active
August 29, 2015 14:16
-
-
Save Nymphium/39b616b9939d93d3a255 to your computer and use it in GitHub Desktop.
Tree Script (http://www.ialab.cs.tsukuba.ac.jp/~maeda/class/oo/treescript.html), written in MoonScript instead Java
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
*.cl |
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
#!/usr/bin/env moon | |
uuid = require "uuid" | |
scanner = require "scanner" | |
vars = setmetatable {}, {__call: (key, val) => self[key] = val} | |
class IntLeaf | |
:value | |
new: (value) => @value = value | |
eval: => self | |
replace: (name, r) => self | |
tostring: => @value | |
class NameLeaf | |
:name | |
new: (name) => @name = name | |
eval: => self | |
replace: (name, r) => name == @name and r or self | |
tostring: => @name | |
class Node | |
:operator | |
:left | |
:right | |
new: (operator, left, right) => | |
@operator = operator | |
@left = left | |
@right = right | |
eval: => @operator\calc @left, @right | |
replace: (name, r) => Node @operator, @left\replace(name, r), @right\replace(name, r) | |
tostring: => "( #{@operator\op_name!} #{@left\tostring!} #{@right\tostring!} )" | |
class BinOp | |
calc: (left, right) => | |
l = left\eval!.value | |
r = right\eval!.value | |
return IntLeaf (@op l, r) | |
class AddOp extends BinOp | |
op_name: => "+" | |
op: (rand1, rand2) => rand1 + rand2 | |
class SubOp extends BinOp | |
op_name: => "-" | |
op: (rand1, rand2) => rand1 - rand2 | |
class MulOp extends BinOp | |
op_name: => "*" | |
op: (rand1, rand2) => rand1 * rand2 | |
class DivOp extends BinOp | |
op_name: => "/" | |
op: (rand1, rand2) => rand1 / rand2 | |
class FunOp | |
op_name: => "fun" | |
calc: (left, right) => Node self, left, right | |
class CallOp | |
op_name: => "call" | |
calc: (left, right) => | |
local fun | |
if vars[left\tostring!] | |
fun = vars[left\tostring!] | |
else | |
fun = left\eval! | |
param = fun.left | |
body = fun.right | |
expression = body\replace param.name, right | |
print "replace: #{expression\tostring!}" if arg[1] == "-v" | |
return expression\eval! | |
class EqOp | |
op_name: => "==" | |
calc: (left, right) => | |
l = left\eval! | |
r = right\eval! | |
ret_left = NameLeaf "left" | |
ret_right = NameLeaf "right" | |
return Node FunOp!, ret_left, Node FunOp!, ret_right, l.value == r.value and ret_left or ret_right | |
class DefOp | |
op_name: => "def" | |
calc: (left, right) => | |
vars left\tostring!, right | |
return left | |
optable = {AddOp!, SubOp!, MulOp!, DivOp!, FunOp!, CallOp!, EqOp!, DefOp!} | |
ops = {} | |
for _, op in pairs optable | |
ops[op\op_name!] = op | |
rename = (t, rename_from, rename_to) -> | |
tcls = t.__class.__name | |
ret = t | |
if tcls == "Node" | |
ret = Node t.operator, rename(t.left, rename_from, rename_to), rename(t.right, rename_from, rename_to) | |
elseif tcls == "NameLeaf" | |
ret = NameLeaf t.name == rename_from and rename_to or t.name | |
return ret | |
parse = -> | |
if scanner\has_next_int! | |
return IntLeaf scanner\next_int! | |
elseif scanner\has_next "%(" | |
scanner\next! | |
name = scanner\next! | |
left = parse! | |
right = parse! | |
if name == "fun" | |
var = left.name | |
renameto = uuid! | |
left = rename left, var, renameto | |
right = rename right, var, renameto | |
scanner\next ")" | |
return Node ops[name], left, right | |
else | |
var = scanner\next! | |
if var == ";" | |
while scanner\has_next "." | |
scanner\next! | |
return parse! | |
return vars[var] or NameLeaf var | |
run = -> | |
while scanner\has_next! | |
t = parse! | |
continue if t\tostring! == nil | |
res = tonumber t\eval!\tostring! | |
if res | |
res = "function: #{t\tostring!}\n" .. res if arg[1] == "-v" | |
print res | |
run! | |
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
split = (str) -> | |
return if not str | |
dim = "[^ ]+" | |
ret = [piece for piece in str\gmatch dim] | |
return ret | |
return class | |
:count | |
:str | |
next: (mat) => | |
if mat and mat != @str[@count] | |
return error "Error: invalid argument" | |
@count += 1 | |
@str[@count - 1] | |
next_int: => | |
@count += 1 | |
tonumber @str[@count - 1] | |
has_next_int: => | |
tonumber @str[@count] | |
has_next: (mat) => | |
return @str[@count] and string.match @str[@count], mat or false if mat | |
@str = split io.read! | |
@count = 1 | |
return false if not @str | |
return true if #@str > 0 | |
@has_next! | |
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
; ( def x 3 ) | |
; ( def x 6 ) | |
; ( def f ( fun g ( * g g ) ) ) | |
; ( call f x ) | |
; ( call ( fun x ( * x ( call ( fun x ( * x x ) ) x ) ) ) 3 ) | |
; ( call ( fun x ( call ( fun y x ) 2 ) ) ( * y y ) ) | |
( def fact ( fun n ( call ( call ( == n 0 ) 1 ) ( * n ( call fact ( - n 1 ) ) ) ) ) ) | |
( def result ( call fact 10 ) ) | |
( + result 10 ) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
used uuid package is here: https://rocks.moonscript.org/modules/tieske/uuid