From ee7c860c53ccca59e63a9f76a23f9560b826a062 Mon Sep 17 00:00:00 2001
From: Lou Knauer <lou.knauer@gmx.de>
Date: Tue, 5 Mar 2019 14:03:51 +0100
Subject: [PATCH] new ??? node for returning contexts

---
 lib/DhallishGrammar.treetop |  3 ++-
 lib/ast.rb                  | 15 ++++++++++++--
 lib/dhallish.rb             | 40 ++++++++++++++++++++++++++++++++++++-
 tests/test_dhallish_ctx.rb  | 13 ++++++++++++
 4 files changed, 67 insertions(+), 4 deletions(-)
 create mode 100644 tests/test_dhallish_ctx.rb

diff --git a/lib/DhallishGrammar.treetop b/lib/DhallishGrammar.treetop
index f88c58e..aa919ff 100644
--- a/lib/DhallishGrammar.treetop
+++ b/lib/DhallishGrammar.treetop
@@ -371,7 +371,8 @@ grammar DhallishGrammar
 		exp:label 				{ def to_node(ctx) exp.to_node(ctx) end } /
 		exp:record_literal                      { def to_node(ctx) exp.to_node(ctx) end } /
 		exp:record_type_literal                 { def to_node(ctx) exp.to_node(ctx) end } /
-		"(" space? exp:expression space? ")"	{ def to_node(ctx) exp.to_node(ctx) end }
+		"(" space? exp:expression space? ")"	{ def to_node(ctx) exp.to_node(ctx) end } /
+		"???" { def to_node(ctx) Dhallish::Ast::GetContext.new end }
 	end
 
 	## End of operator expressions
diff --git a/lib/ast.rb b/lib/ast.rb
index 744fce8..84aead7 100644
--- a/lib/ast.rb
+++ b/lib/ast.rb
@@ -690,12 +690,12 @@ module Dhallish
 		class Literal_Node
 			attr_accessor :val
 			attr_accessor :type
-			
+
 			def initialize(val, type)
 				@val = val
 				@type = type
 			end
-			
+
 			def compute_type(ctx)
 				@type
 			end
@@ -705,5 +705,16 @@ module Dhallish
 			end
 		end
 
+		class GetContext
+			def initialize() @typectx = nil end
+
+			def compute_type(ctx)
+				@typectx = ctx
+				Types::Record.new({})
+			end
+
+			def evaluate(ctx) { "#valctx#" => ctx, "#typectx#" => @typectx } end
+		end
+
 	end
 end
diff --git a/lib/dhallish.rb b/lib/dhallish.rb
index e35cf09..5af922b 100644
--- a/lib/dhallish.rb
+++ b/lib/dhallish.rb
@@ -24,6 +24,13 @@ module Dhallish
 			::Dhallish::fill_context(@context, @typectx)
 		end
 
+		def evaluate_file(file, ctx = @context, typectx = @typectx)
+			file = File.open(file)
+			res = evaluate(file.read, ctx, typectx)
+			file.close
+			res
+		end
+
 		def evaluate(dhallcode, ctx = @context, typectx = @typectx)
 			treetopast = @parser.parse dhallcode
 			if treetopast.nil?
@@ -32,11 +39,42 @@ module Dhallish
 
 			ast = treetopast.to_node nil
 			type = ast.compute_type typectx
-			#puts type
 
 			return [ast.evaluate(ctx), type]
 		end
 
+		def create_ctx_from_file(file)
+			file = File.open(file)
+			res = create_ctx(file.read)
+			file.close
+			res
+		end
+
+		def create_ctx(dhallcode)
+			val, type = evaluate(dhallcode, @context, @typectx)
+			if !type.is_a? Types::Record or val["#valctx#"].nil? or val["#typectx#"].nil?
+				raise DhallError, "Dhallish: create_ctx did not return a context! use `???` as a return expression in dhallish for create_ctx"
+			end
+			val
+		end
+
+		def evaluate_in_ctx_from_file(file, dhallctx)
+			file = File.open(file)
+			res = evaluate_in_ctx(file.read, dhallctx)
+			file.close
+			res
+		end
+
+		def evaluate_in_ctx(dhallcode, dhallctx)
+			if !dhallctx.is_a? Hash or dhallctx["#valctx#"].nil? or dhallctx["#typectx#"].nil?
+				raise DhallError, "Dhallish: evaluate_in_ctx must be called with a context returned by create_ctx"
+			end
+			typectx = dhallctx["#typectx#"]
+			valctx = dhallctx["#valctx#"]
+
+			val, type = evaluate(dhallcode, valctx, typectx)
+			val
+		end
 	end
 
 end
diff --git a/tests/test_dhallish_ctx.rb b/tests/test_dhallish_ctx.rb
new file mode 100644
index 0000000..bff3cd5
--- /dev/null
+++ b/tests/test_dhallish_ctx.rb
@@ -0,0 +1,13 @@
+require_relative '../lib/dhallish.rb'
+
+dhall = Dhallish::Dhallish.new
+
+ctx = dhall.create_ctx("
+let x = 41
+let f = \\(n: Natural) -> n + 1
+in ???
+")
+
+res = dhall.evaluate_in_ctx("f x", ctx)
+
+puts res
-- 
GitLab