local n=require(script.Parent.Constants)local W=require(script.Parent.Functions)local function Y(n,Y)return W[n](table.unpack(Y))end local function v(W,Y)return Y[W]or n[W]or error(string.format("\'\037\115\' \105\115 \110\111\116 \100\101\102\105\110\101\100",W))end local function g(n,W,Y)if n=="\043"then return W+Y elseif n=="-"then return W-Y elseif n=="\042"then return W*Y elseif n=="\047"then return W/Y elseif n=="\037"then return W%Y elseif n=="\094"then return W^Y end end local function N(n,W)if n=="-"then return-W end return W end local function m(n,W,Y)local v={}for n,g in ipairs(n)do table.insert(v,W(g,Y))end return v end local function j(n,W)if n.kind=="\078\117\109\098\101\114"then return n.value elseif n.kind=="\086\097\114\105\097\098\108\101"then return v(n.identifier,W)elseif n.kind=="\070\117\110\099\116\105\111\110 \067\097\108\108"then return Y(n.identifier,m(n.arguments,j,W))elseif n.kind=="\066\105\110\097\114\121 \079\112\101\114\097\116\105\111\110"then return g(n.operator,j(n.left,W),j(n.right,W))elseif n.kind=="\085\110\097\114\121 \079\112\101\114\097\116\105\111\110"then return N(n.operator,j(n.value,W))end end return j
local Constants = require(script.Parent.Constants)
local Functions = require(script.Parent.Functions)

local function solveFunctionCall(name, arguments)
	return Functions[name](table.unpack(arguments))
end

local function solveVariable(name, variables)
	return variables[name] or Constants[name] or error(string.format("'%s' is not defined", name))
end

local function solveBinaryOperation(operator, left, right)
	if operator == "+" then
		return left + right
	elseif operator == "-" then
		return left - right
	elseif operator == "*" then
		return left * right
	elseif operator == "/" then
		return left / right
	elseif operator == "%" then
		return left % right
	elseif operator == "^" then
		return left ^ right
	end
end

local function solveUnaryOperation(operator, value)
	if operator == "-" then
		return -value
	end

	return value
end

local function solveArguments(arguments, solve, variables)
	local solvedArguments = {}

	for _, argument in ipairs(arguments) do
		table.insert(solvedArguments, solve(argument, variables))
	end

	return solvedArguments
end

local function solve(node, variables)
	if node.kind == "Number" then
		return node.value
	elseif node.kind == "Variable" then
		return solveVariable(node.identifier, variables)
	elseif node.kind == "Function Call" then
		return solveFunctionCall(node.identifier, solveArguments(node.arguments, solve, variables))
	elseif node.kind == "Binary Operation" then
		return solveBinaryOperation(node.operator, solve(node.left, variables), solve(node.right, variables))
	elseif node.kind == "Unary Operation" then
		return solveUnaryOperation(node.operator, solve(node.value, variables))
	end
end

return solve
