From 1e9d4f30ec1c82cd7dbf2bbaf6c67d8fc6f0d97e Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Fri, 29 Mar 2019 20:06:18 -0500 Subject: [PATCH] Refactor RecordProjection typecheck --- lib/dhall/ast.rb | 12 ++++++++++++ lib/dhall/typecheck.rb | 18 ++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/dhall/ast.rb b/lib/dhall/ast.rb index 551ab6f..a64bc9b 100644 --- a/lib/dhall/ast.rb +++ b/lib/dhall/ast.rb @@ -443,6 +443,14 @@ module Dhall }.sort]) end + def keys + record.keys + end + + def slice(keys) + RecordType.for(record.select { |k, _| keys.include?(k) }) + end + def ==(other) other.respond_to?(:record) && record.to_a == other.record.to_a end @@ -459,6 +467,10 @@ module Dhall class EmptyRecordType < RecordType include(ValueSemantics.for_attributes {}) + def slice(*) + self + end + def record {} end diff --git a/lib/dhall/typecheck.rb b/lib/dhall/typecheck.rb index 0193495..fcaab6e 100644 --- a/lib/dhall/typecheck.rb +++ b/lib/dhall/typecheck.rb @@ -587,25 +587,23 @@ module Dhall class RecordProjection def initialize(projection) @projection = projection - @record = projection.record + @record = TypeChecker.for(projection.record) @selectors = projection.selectors end def annotate(context) - arecord = TypeChecker.for(@record).annotate(context) + arecord = @record.annotate(context) - unless arecord.type.class == Dhall::RecordType - raise TypeError, "RecordProjection on #{arecord.type}" - end + TypeChecker.assert arecord.type.class.name, "Dhall::RecordType", + "RecordProjection on #{arecord.type}" - slice = arecord.type.record.select { |k, _| @selectors.include?(k) } - if slice.size != @selectors.length - raise TypeError, "#{arecord.type} missing one of: #{@selectors}" - end + slice = arecord.type.slice(@selectors) + TypeChecker.assert slice.keys, @selectors, + "#{arecord.type} missing one of: #{@selectors}" Dhall::TypeAnnotation.new( value: @projection.with(record: arecord), - type: Dhall::RecordType.for(slice) + type: slice ) end end -- 2.34.5