Skip to content

Instantly share code, notes, and snippets.

@Nymphium
Last active August 29, 2015 14:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nymphium/39b616b9939d93d3a255 to your computer and use it in GitHub Desktop.
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
#!/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!
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!
; ( 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 )
@Nymphium
Copy link
Author

Nymphium commented Mar 2, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment