<commit_before>module(..., package.seeall)

local util = require('tundra.util')
local path = require('tundra.path')
local depgraph = require('tundra.depgraph')

--[==[

The environment is a holder for variables and their associated values. Values
are always kept as tables, even if there is only a single value.

FOO = { a b c }

e:interpolate("$(FOO)") -> "a b c"
e:interpolate("$(FOO:j, )") -> "a, b, c"
e:interpolate("$(FOO:p-I)") -> "-Ia -Ib -Ic"

Missing keys trigger errors unless a default value is specified.

]==]--

local envclass = {}

function envclass:create(parent, assignments, obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self

	obj.vars = {}
	obj.parent = parent
	obj.memos = {}
	obj.memo_keys = {}

	-- set up the table of make functions
	obj._make = {} 
	obj.make = setmetatable({}, {
		__index = function(table, key) return obj:_lookup_make(key) end,
		__newindex = function(table, key, value) obj:register_make_fn(key, value) end
	})

	-- assign initial bindings
	if assignments then
		obj:set_many(assignments)
	end

	return obj
end

function envclass:clone(assignments)
	return envclass:create(self, assignments)
end

function envclass:_lookup_make(name, real_env)
	real_env = real_env or self
	local entry = self._make[name]
	if entry then
		assert(entry.Name == name)
		local fn = function(args)
			return entry.Function(real_env, args)
		end
		return fn
	elseif self.parent then
		return self.parent:_lookup_make(name, real_env)
	else
		error("'" .. name .. "': no such make function", 2)
	end
end

function envclass:register_make_fn(name, fn, docstring)
	assert(type(name) == "string")
	assert(type(fn) == "function")
	self._make[name] = {
		Name = name,
		Function = fn,
		Doc = docstring or ""
	}
end

function envclass:register_implicit_make_fn(ext, fn, docstring)
	assert(type(ext) == "string")
	assert(type(fn) == "function")
	if not ext:match("^%.") then
		ext = "." .. ext -- we want the dot in the extension
	end

	if not self._implicit_exts then
		self._implicit_exts = {}
	end
	self._implicit_exts[ext] = {
		Function = fn,
		Doc = docstring or "",
	}
end

function envclass:get_implicit_make_fn(filename)
	local ext = path.get_extension(filename)
	local chain = self
	while chain do
		local t = chain._implicit_exts
		if t then
			local v = t[ext]
			if v then return v.Function end
		end
		chain = chain.parent
	end
	return nil
end

function envclass:has_key(key)<commit_msg>Removed env.make support now that the declarative frontend works so well.<commit_after>module(..., package.seeall)

local util = require('tundra.util')
local path = require('tundra.path')
local depgraph = require('tundra.depgraph')

--[==[

The environment is a holder for variables and their associated values. Values
are always kept as tables, even if there is only a single value.

FOO = { a b c }

e:interpolate("$(FOO)") -> "a b c"
e:interpolate("$(FOO:j, )") -> "a, b, c"
e:interpolate("$(FOO:p-I)") -> "-Ia -Ib -Ic"

Missing keys trigger errors unless a default value is specified.

]==]--

local envclass = {}

function envclass:create(parent, assignments, obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self

	obj.vars = {}
	obj.parent = parent
	obj.memos = {}
	obj.memo_keys = {}

	-- assign initial bindings
	if assignments then
		obj:set_many(assignments)
	end

	return obj
end

function envclass:clone(assignments)
	return envclass:create(self, assignments)
end

function envclass:register_implicit_make_fn(ext, fn, docstring)
	if type(ext) ~= "string" then
		errorf("extension must be a string")
	end
	if type(fn) ~= "function" then
		errorf("fn must be a function")
	end

	if not ext:match("^%.") then
		ext = "." .. ext -- we want the dot in the extension
	end

	if not self._implicit_exts then
		self._implicit_exts = {}
	end

	self._implicit_exts[ext] = {
		Function = fn,
		Doc = docstring or "",
	}
end

function envclass:get_implicit_make_fn(filename)
	local ext = path.get_extension(filename)
	local chain = self
	while chain do
		local t = chain._implicit_exts
		if t then
			local v = t[ext]
			if v then return v.Function end
		end
		chain = chain.parent
	end
	return nil
end

function envclass:has_key(key)
{'fraction_non_alphanumeric': 0.12607655502392345, 'fraction_numerical': 0.00023923444976076556, 'mean_word_length': 4.025240384615385, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7635012', 'n_tokens_mistral': 1526, 'n_tokens_neox': 1463, 'n_words': 439}