74 lines
1.6 KiB
Ruby
74 lines
1.6 KiB
Ruby
require_relative 'node'
|
|
|
|
module Dentaku
|
|
module AST
|
|
class Function < Node
|
|
def initialize(*args)
|
|
@args = args
|
|
end
|
|
|
|
def dependencies(context={})
|
|
@args.flat_map { |a| a.dependencies(context) }
|
|
end
|
|
|
|
def self.get(name)
|
|
registry.fetch(function_name(name)) {
|
|
fail ParseError, "Undefined function #{ name }"
|
|
}
|
|
end
|
|
|
|
def self.register(name, type, implementation)
|
|
function = Class.new(self) do
|
|
def self.implementation=(impl)
|
|
@implementation = impl
|
|
end
|
|
|
|
def self.implementation
|
|
@implementation
|
|
end
|
|
|
|
def self.type=(type)
|
|
@type = type
|
|
end
|
|
|
|
def self.type
|
|
@type
|
|
end
|
|
|
|
def value(context={})
|
|
args = @args.map { |a| a.value(context) }
|
|
self.class.implementation.call(*args)
|
|
end
|
|
|
|
def type
|
|
self.class.type
|
|
end
|
|
end
|
|
|
|
function_class = name.to_s.capitalize
|
|
Dentaku::AST.send(:remove_const, function_class) if Dentaku::AST.const_defined?(function_class)
|
|
Dentaku::AST.const_set(function_class, function)
|
|
|
|
function.implementation = implementation
|
|
function.type = type
|
|
|
|
registry[function_name(name)] = function
|
|
end
|
|
|
|
def self.register_class(name, function_class)
|
|
registry[function_name(name)] = function_class
|
|
end
|
|
|
|
private
|
|
|
|
def self.function_name(name)
|
|
name.to_s.downcase
|
|
end
|
|
|
|
def self.registry
|
|
@registry ||= {}
|
|
end
|
|
end
|
|
end
|
|
end
|