def process_defn(exp)
name = exp.shift
unprocessed_args = exp.shift
args = body = function_type = nil
@env.scope do
args = process unprocessed_args
begin
body = process exp.shift
rescue TypeError => err
puts "Error in method #{name}, trying to unify, whole body blew out"
raise
end
function_type = Type.function Type.unknown, args.sexp_types, Type.unknown
@functions.unify(name, function_type) do
@functions.add_function(name, function_type)
$stderr.puts "\nWARNING: Registering function #{name}: #{function_type.inspect}" if $DEBUG
end
end
return_type = function_type.list_type.return_type
return_count = 0
body.each_of_type(:return) do |sub_exp|
begin
return_type.unify sub_exp[1].sexp_type
return_count += 1
rescue TypeError => err
puts "Error in method #{name}, trying to unify #{sub_exp.inspect} against #{return_type.inspect}"
raise
end
end
if return_count == 0 then
begin
return_type.unify Type.void
rescue TypeError => err
puts "Error in method #{name}, trying to unify #{function_type.inspect} against Type.void"
raise
end
end
raise "wrong" if
args.sexp_types.size != function_type.list_type.formal_types.size
args.sexp_types.each_with_index do |type, i|
type.unify function_type.list_type.formal_types[i]
end
return t(:defn, name, args, body, function_type)
end