chalk/src/chalk/tree.cr

309 lines
6.4 KiB
Crystal

module Chalk
module Trees
# A class used to visit nodes of a tree.
class Visitor
def visit(tree)
end
def finish(tree)
end
end
# A class used to transform a tree, bottom up.
# "Modern Compiler Design" refers to this technique
# as BURS.
class Transformer
def transform(tree)
return tree
end
end
class Reducer(T)
def reduce(tree, children)
end
end
# The base class of a tree.
class Tree
def accept(v)
v.visit(self)
v.finish(self)
end
def apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
return r.reduce(self, [] of T)
end
end
# A tree that represents an ID.
class TreeId < Tree
property id : String
def initialize(@id)
end
end
# A tree that represents an integer literal.
class TreeLit < Tree
property lit : Int64
def initialize(@lit)
end
end
# A tree that represents a function call.
class TreeCall < Tree
property name : String
property params : Array(Tree)
def initialize(@name, @params)
end
def accept(v)
v.visit(self)
@params.each &.accept(v)
v.finish(self)
end
def apply(t)
@params.map! do |param|
param.apply(t)
end
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
return r.reduce(self, @params.map &.reduce(r))
end
end
# A tree that represents an operation on two values.
class TreeOp < Tree
property op : Compiler::TokenType
property left : Tree
property right : Tree
def initialize(@op, @left, @right)
end
def accept(v)
v.visit(self)
@left.accept(v)
@right.accept(v)
v.finish(self)
end
def apply(t)
@left = @left.apply(t)
@right = @right.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
return r.reduce(self, [@left.reduce(r), @right.reduce(r)])
end
end
# A tree that represents a block of statements.
class TreeBlock < Tree
property children : Array(Tree)
def initialize(@children)
end
def accept(v)
v.visit(self)
@children.each &.accept(v)
v.finish(self)
end
def apply(t)
@children.map! do |child|
child.apply(t)
end
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
return r.reduce(self, @children.map &.reduce(r))
end
end
# A tree that represents a function declaration.
class TreeFunction < Tree
property name : String
property params : Array(String)
property block : Tree
getter type
def initialize(@name, @params, return_type : Compiler::Type, @block)
@type = Compiler::FunctionType.new([Compiler::Type::U8] * @params.size, return_type)
end
def param_count
return @params.size
end
def accept(v)
v.visit(self)
@block.accept(v)
v.finish(self)
end
def apply(t)
@block = @block.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
return r.reduce(self, [@block.reduce(r)])
end
end
# A tree that represents the declaration of
# a new variable.
class TreeVar < Tree
property name : String
property expr : Tree
def initialize(@name, @expr)
end
def accept(v)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
def apply(t)
@expr = @expr.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
r.reduce(self, [@expr.reduce(r)])
end
end
# A tree that represents the assignment
# to an existing variable.
class TreeAssign < Tree
property name : String
property expr : Tree
def initialize(@name, @expr)
end
def accept(v)
v.visit(self)
@expr.accept(v)
v.finish(self)
end
def apply(t)
@expr = @expr.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
r.reduce(self, [@expr.reduce(r)])
end
end
# A tree that represents an if statement.
class TreeIf < Tree
property condition : Tree
property block : Tree
property otherwise : Tree?
def initialize(@condition, @block, @otherwise = nil)
end
def accept(v)
v.visit(self)
@condition.accept(v)
@block.accept(v)
@otherwise.try &.accept(v)
v.finish(self)
end
def apply(t)
@condition = @condition.apply(t)
@block = @block.apply(t)
@otherwise = @otherwise.try &.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
cond = @condition.reduce(r)
blk = @block.reduce(r)
if other = @otherwise
r.reduce(self, [cond, blk,other.reduce(r)])
else
r.reduce(self, [cond, blk])
end
end
end
# A tree that represents a while loop.
class TreeWhile < Tree
property condition : Tree
property block : Tree
def initialize(@condition, @block)
end
def accept(v)
v.visit(self)
@condition.accept(v)
@block.accept(v)
v.finish(self)
end
def apply(t)
@condition = @condition.apply(t)
@block = @block.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
r.reduce(self, [@condition.reduce(r), @block.reduce(r)])
end
end
# A tree that represents a return statement.
class TreeReturn < Tree
property rvalue : Tree
def initialize(@rvalue)
end
def accept(v)
v.visit(self)
@rvalue.accept(v)
v.finish(self)
end
def apply(t)
@rvalue = @rvalue.apply(t)
return t.transform(self)
end
def reduce(r : Reducer(T)) forall T
r.reduce(self, [@rvalue.reduce(r)])
end
end
class TreeSprite < Tree
property name : String
property sprite : Compiler::Sprite
def initialize(@name, @sprite)
end
end
end
end