mirror of
				https://github.com/Reuh/anselme.git
				synced 2025-10-27 16:49:31 +00:00 
			
		
		
		
	Changed a few things
- Bumped to 0.15.0 - Add boot script - Change variable definition syntax, using a = to distinguish more cleary between identifier and value - Variables initial values are evaluated on first use instead of at parsing time - Error on variable redefinition. Means you should make sure to load saves after your scripts. - Improve string parsing, support for escape codes - Remove support for number literals with empty decimal part (42. for 42.0) as there's no distinction in Anselme and it conflicts with .function call suffix - Changed priority of : pair operator - Add type type, and type annotations to variables and function parameters - Change Lua function system to use regular Anselme functions - Defining a function from Lua is now way simpler and require providing a full Anselme function signature - Change Anselme function system - Dynamic dispatch, based on arity, type annotation and parameter names. Will select the most specific function at runtime. - Define way to overload most operators - Allow custom type to text formatters - Allow assignment to custom functions - Index operator ( renamed to () - Functions with parameters each have their own private namespace (scoping ersatz) - Internal: "custom"-mode operators now have their own expression AST type instead of cluttering the function system - Remove static type checker as it is barely useful with new function system. May or may not rewrite one in the future. - Improve error messages here and there - Internal: cleaning
This commit is contained in:
		
							parent
							
								
									4b139019c9
								
							
						
					
					
						commit
						64bc85741a
					
				
					 86 changed files with 2096 additions and 1012 deletions
				
			
		
							
								
								
									
										12
									
								
								stdlib/bootscript.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								stdlib/bootscript.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| return [[ | ||||
| (Built-in type definition) | ||||
| :nil="nil" | ||||
| :number="number" | ||||
| :string="string" | ||||
| :list="list" | ||||
| :pair="pair" | ||||
| 
 | ||||
| (Default formatter: doesn't do anything and let built-in formatters do the job) | ||||
| $ format(v) | ||||
| 	@v | ||||
| ]] | ||||
|  | @ -1,421 +1,222 @@ | |||
| local truthy, eval, find_function_variant, anselme | ||||
| 
 | ||||
| local function rewrite_assignement(fqm, state, arg, explicit_call) | ||||
| 	local op, e = find_function_variant(fqm:match("^(.*)%=$"), state, arg, true) | ||||
| 	if not op then return op, e end | ||||
| 	local ass, err = find_function_variant(":=", state, { type = "list", left = arg.left, right = op }, explicit_call) | ||||
| 	if not ass then return ass, err end | ||||
| 	return ass | ||||
| end | ||||
| 
 | ||||
| local function compare(a, b) | ||||
| 	if a.type ~= b.type then | ||||
| 		return false | ||||
| 	end | ||||
| 	if a.type == "pair" then | ||||
| 		return compare(a.value[1], b.value[1]) and compare(a.value[2], b.value[2]) | ||||
| 	elseif a.type == "list" then | ||||
| 		if #a.value ~= #b.value then | ||||
| 			return false | ||||
| 		end | ||||
| 		for i, v in ipairs(a.value) do | ||||
| 			if not compare(v, b.value[i]) then | ||||
| 				return false | ||||
| 			end | ||||
| 		end | ||||
| 		return true | ||||
| 	else | ||||
| 		return a.value == b.value | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| local numeric_index | ||||
| local string_index | ||||
| local truthy, anselme, compare, is_of_type | ||||
| 
 | ||||
| local functions | ||||
| functions = { | ||||
| 	-- discard left | ||||
| 	[";"] = { | ||||
| 		{ | ||||
| 			arity = 2, mode = "raw", | ||||
| 			value = function(a, b) return b end | ||||
| 		} | ||||
| 	}, | ||||
| 	-- assignement | ||||
| 	[":="] = { | ||||
| 		-- assign to numeric index | ||||
| 		{ | ||||
| 			arity = 2, mode = "custom", | ||||
| 			check = function(state, args) | ||||
| 				local left = args[1] | ||||
| 				return left.type == "function" and left.variant == numeric_index and left.argument.expression.left.type == "variable" | ||||
| 			end, | ||||
| 			value = function(state, exp) | ||||
| 				local arg = exp.argument.expression | ||||
| 				local name = arg.left.argument.expression.left.name | ||||
| 				local index, indexe = eval(state, arg.left.argument.expression.right) | ||||
| 				if not index then return index, indexe end | ||||
| 				local right, righte = eval(state, arg.right) | ||||
| 				if not right then return right, righte end | ||||
| 				state.variables[name].value[index.value] = right | ||||
| 				return right | ||||
| 			end | ||||
| 		}, | ||||
| 		-- assign to string index | ||||
| 		{ | ||||
| 			arity = 2, mode = "custom", | ||||
| 			check = function(state, args) | ||||
| 				local left = args[1] | ||||
| 				return left.type == "function" and left.variant == string_index and left.argument.expression.left.type == "variable" | ||||
| 			end, | ||||
| 			value = function(state, exp) | ||||
| 				local arg = exp.argument.expression | ||||
| 				local name = arg.left.argument.expression.left.name | ||||
| 				local index, indexe = eval(state, arg.left.argument.expression.right) | ||||
| 				if not index then return index, indexe end | ||||
| 				local right, righte = eval(state, arg.right) | ||||
| 				if not right then return right, righte end | ||||
| 				-- update index | ||||
| 				local list = state.variables[name].value | ||||
| 				for _,v in ipairs(list) do | ||||
| 					if v.type == "pair" and compare(v.value[1], index) then | ||||
| 						v.value[2] = right | ||||
| 						return right | ||||
| 					end | ||||
| 				end | ||||
| 				-- new index | ||||
| 				table.insert(list, { | ||||
| 					type = "pair", | ||||
| 					value = { index, right } | ||||
| 				}) | ||||
| 				return right | ||||
| 			end | ||||
| 		}, | ||||
| 		-- assign to direct variable | ||||
| 		{ | ||||
| 			arity = 2, mode = "custom", | ||||
| 			check = function(state, args) | ||||
| 				local left, right = args[1], args[2] | ||||
| 				if left.type ~= "variable" then | ||||
| 					return nil, ("assignement expected a variable as a left argument but received a %s"):format(left.type) | ||||
| 				end | ||||
| 				if left.return_type and right.return_type and left.return_type ~= right.return_type then | ||||
| 					return nil, ("trying to assign a %s value to a %s variable"):format(right.return_type, left.return_type) | ||||
| 				end | ||||
| 				return right.return_type or true | ||||
| 			end, | ||||
| 			value = function(state, exp) | ||||
| 				local arg = exp.argument.expression | ||||
| 				local name = arg.left.name | ||||
| 				local right, righte = eval(state, arg.right) | ||||
| 				if not right then return right, righte end | ||||
| 				state.variables[name] = right | ||||
| 				return right | ||||
| 			end | ||||
| 		} | ||||
| 	}, | ||||
| 	["+="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["-="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["*="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["/="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["//="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["%="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	}, | ||||
| 	["^="] = { | ||||
| 		{ rewrite = rewrite_assignement } | ||||
| 	[";(a, b)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a, b) return b end | ||||
| 	}, | ||||
| 	-- comparaison | ||||
| 	["=="] = { | ||||
| 		{ | ||||
| 			arity = 2, return_type = "number", mode = "raw", | ||||
| 			value = function(a, b) | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = compare(a, b) and 1 or 0 | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	["==(a, b)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a, b) | ||||
| 			return { | ||||
| 				type = "number", | ||||
| 				value = compare(a, b) and 1 or 0 | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	["!="] = { | ||||
| 		{ | ||||
| 			arity = 2, return_type = "number", mode = "raw", | ||||
| 			value = function(a, b) | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = compare(a, b) and 0 or 1 | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	}, | ||||
| 	[">"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a > b end | ||||
| 		} | ||||
| 	}, | ||||
| 	["<"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a < b end | ||||
| 		} | ||||
| 	}, | ||||
| 	[">="] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a >= b end | ||||
| 		} | ||||
| 	}, | ||||
| 	["<="] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a <= b end | ||||
| 		} | ||||
| 	["!=(a, b)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a, b) | ||||
| 			return { | ||||
| 				type = "number", | ||||
| 				value = compare(a, b) and 0 or 1 | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	[">(a::number, b::number)"] = function(a, b) return a > b end, | ||||
| 	["<(a::number, b::number)"] = function(a, b) return a < b end, | ||||
| 	[">=(a::number, b::number)"] = function(a, b) return a >= b end, | ||||
| 	["<=(a::number, b::number)"] = function(a, b) return a <= b end, | ||||
| 	-- arithmetic | ||||
| 	["+"] = { | ||||
| 		{ | ||||
| 			arity = 2, | ||||
| 			value = function(a, b) | ||||
| 				if type(a) == "string" then | ||||
| 					return a .. b | ||||
| 				else | ||||
| 					return a + b | ||||
| 				end | ||||
| 			end | ||||
| 		} | ||||
| 	}, | ||||
| 	["-"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a - b end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 1, types = { "number" }, return_type = "number", | ||||
| 			value = function(a) return -a end | ||||
| 		} | ||||
| 	}, | ||||
| 	["*"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a * b end | ||||
| 		} | ||||
| 	}, | ||||
| 	["/"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a / b end | ||||
| 		} | ||||
| 	}, | ||||
| 	["//"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return math.floor(a / b) end | ||||
| 		} | ||||
| 	}, | ||||
| 	["^"] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) return a ^ b end | ||||
| 		} | ||||
| 	}, | ||||
| 	["+(a::number, b::number)"] = function(a, b) return a + b end, | ||||
| 	["+(a::string, b::string)"] = function(a, b) return a .. b end, | ||||
| 	["-(a::number, b::number)"] = function(a, b) return a - b end, | ||||
| 	["-(a::number)"] = function(a) return -a end, | ||||
| 	["*(a::number, b::number)"] = function(a, b) return a * b end, | ||||
| 	["/(a::number, b::number)"] = function(a, b) return a / b end, | ||||
| 	["//(a::number, b::number)"] = function(a, b) return math.floor(a / b) end, | ||||
| 	["^(a::number, b::number)"] = function(a, b) return a ^ b end, | ||||
| 	-- boolean | ||||
| 	["!"] = { | ||||
| 		{ | ||||
| 			arity = 1, return_type = "number", mode = "raw", | ||||
| 			value = function(a) | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = truthy(a) and 0 or 1 | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	}, | ||||
| 	["&"] = { | ||||
| 		{ | ||||
| 			arity = 2, return_type = "number", mode = "custom", | ||||
| 			value = function(state, exp) | ||||
| 				local arg = exp.argument.expression | ||||
| 				local left, lefte = eval(state, arg.left) | ||||
| 				if not left then return left, lefte end | ||||
| 				if truthy(left) then | ||||
| 					local right, righte = eval(state, arg.right) | ||||
| 					if not right then return right, righte end | ||||
| 					if truthy(right) then | ||||
| 						return { | ||||
| 							type = "number", | ||||
| 							value = 1 | ||||
| 						} | ||||
| 					end | ||||
| 				end | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = 0 | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	}, | ||||
| 	["|"] = { | ||||
| 		{ | ||||
| 			arity = 2, return_type = "number", mode = "custom", | ||||
| 			value = function(state, exp) | ||||
| 				local arg = exp.argument.expression | ||||
| 				local left, lefte = eval(state, arg.left) | ||||
| 				if not left then return left, lefte end | ||||
| 				if truthy(left) then | ||||
| 					return { | ||||
| 						type = "number", | ||||
| 						value = 1 | ||||
| 					} | ||||
| 				end | ||||
| 				local right, righte = eval(state, arg.right) | ||||
| 				if not right then return right, righte end | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = truthy(right) and 1 or 0 | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	["!(a)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a) | ||||
| 			return { | ||||
| 				type = "number", | ||||
| 				value = truthy(a) and 0 or 1 | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	-- pair | ||||
| 	[":"] = { | ||||
| 		{ | ||||
| 			arity = 2, return_type = "pair", mode = "raw", | ||||
| 			value = function(a, b) | ||||
| 				return { | ||||
| 					type = "pair", | ||||
| 					value = { a, b } | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	[":(a, b)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a, b) | ||||
| 			return { | ||||
| 				type = "pair", | ||||
| 				value = { a, b } | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	-- type | ||||
| 	["::(a, b)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(a, b) | ||||
| 			return { | ||||
| 				type = "type", | ||||
| 				value = { a, b } | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	-- index | ||||
| 	["("] = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "list", "number" }, mode = "raw", | ||||
| 			value = function(a, b) | ||||
| 				return a.value[b.value] or { type = "nil", value = nil } | ||||
| 			end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 2, types = { "list", "string" }, mode = "raw", | ||||
| 			value = function(a, b) | ||||
| 				for _,v in ipairs(a.value) do | ||||
| 					if v.type == "pair" and compare(v.value[1], b) then | ||||
| 						return v.value[2] | ||||
| 					end | ||||
| 	["()(l::list, i::number)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(l, i) | ||||
| 			return l.value[i.value] or { type = "nil", value = nil } | ||||
| 		end | ||||
| 	}, | ||||
| 	["()(l::list, i::string)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(l, i) | ||||
| 			for _, v in ipairs(l.value) do | ||||
| 				if v.type == "pair" and compare(v.value[1], i) then | ||||
| 					return v.value[2] | ||||
| 				end | ||||
| 				return { type = "nil", value = nil } | ||||
| 			end | ||||
| 		} | ||||
| 			return { type = "nil", value = nil } | ||||
| 		end | ||||
| 	}, | ||||
| 	-- index assignment | ||||
| 	["()(l::list, i::number) := v"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(l, i, v) | ||||
| 			local lv = l.type == "type" and l.value[1] or l | ||||
| 			local iv = i.type == "type" and i.value[1] or i | ||||
| 			lv.value[iv.value] = v | ||||
| 			return v | ||||
| 		end | ||||
| 	}, | ||||
| 	["()(l::list, k::string) := v"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(l, k, v) | ||||
| 			local lv = l.type == "type" and l.value[1] or l | ||||
| 			local kv = k.type == "type" and k.value[1] or k | ||||
| 			-- update index | ||||
| 			for _, x in ipairs(lv.value) do | ||||
| 				if x.type == "pair" and compare(x.value[1], kv) then | ||||
| 					x.value[2] = v | ||||
| 					return v | ||||
| 				end | ||||
| 			end | ||||
| 			-- new index | ||||
| 			table.insert(lv.value, { | ||||
| 				type = "pair", | ||||
| 				value = { kv, v } | ||||
| 			}) | ||||
| 			return v | ||||
| 		end | ||||
| 	}, | ||||
| 	-- pair methods | ||||
| 	name = { | ||||
| 		{ | ||||
| 			arity = 1, types = { "pair" }, mode = "raw", | ||||
| 			value = function(a) | ||||
| 				return a.value[1] | ||||
| 			end | ||||
| 		} | ||||
| 	["name(p::pair)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(a) | ||||
| 			return a.value[1] | ||||
| 		end | ||||
| 	}, | ||||
| 	value = { | ||||
| 		{ | ||||
| 			arity = 1, types = { "pair" }, mode = "raw", | ||||
| 			value = function(a) | ||||
| 				return a.value[2] | ||||
| 			end | ||||
| 		} | ||||
| 	["value(p::pair)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(a) | ||||
| 			return a.value[2] | ||||
| 		end | ||||
| 	}, | ||||
| 	-- list methods | ||||
| 	len = { | ||||
| 		{ | ||||
| 			arity = 1, types = { "list" }, return_type = "number", mode = "raw", -- raw to count pairs in the list | ||||
| 			value = function(a) | ||||
| 				return { | ||||
| 					type = "number", | ||||
| 					value = #a.value | ||||
| 				} | ||||
| 			end | ||||
| 		} | ||||
| 	["len(l::list)"] = { | ||||
| 		mode = "untyped raw", -- raw to count pairs in the list | ||||
| 		value = function(a) | ||||
| 			return { | ||||
| 				type = "number", | ||||
| 				value = #a.value | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	insert = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "list" }, return_type = "list", mode = "raw", | ||||
| 			value = function(a, v) | ||||
| 				table.insert(a.value, v) | ||||
| 				return a | ||||
| 			end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 3, types = { "list", "number" }, return_type = "list", mode = "raw", | ||||
| 			value = function(a, k, v) | ||||
| 				table.insert(a.value, k.value, v) | ||||
| 				return a | ||||
| 			end | ||||
| 		} | ||||
| 	["insert(l::list, v)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(l, v) | ||||
| 			local lv = l.type == "type" and l.value[1] or l | ||||
| 			table.insert(lv.value, v) | ||||
| 		end | ||||
| 	}, | ||||
| 	remove = { | ||||
| 		{ | ||||
| 			arity = 1, types = { "list" }, return_type = "list", mode = "raw", | ||||
| 			value = function(a) | ||||
| 				table.remove(a.value) | ||||
| 				return a | ||||
| 			end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 2, types = { "list", "number" }, return_type = "list", mode = "raw", | ||||
| 			value = function(a, k) | ||||
| 				table.remove(a.value, k.value) | ||||
| 				return a | ||||
| 			end | ||||
| 		} | ||||
| 	["insert(l::list, i::number, v)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(l, i, v) | ||||
| 			local lv = l.type == "type" and l.value[1] or l | ||||
| 			local iv = i.type == "type" and i.value[1] or i | ||||
| 			table.insert(lv.value, iv.value, v) | ||||
| 		end | ||||
| 	}, | ||||
| 	find = { | ||||
| 		{ | ||||
| 			arity = 2, types = { "list" }, return_type = "number", mode = "raw", | ||||
| 			value = function(a, v) | ||||
| 				for i, x in ipairs(v.value) do | ||||
| 					if compare(v, x) then | ||||
| 						return i | ||||
| 					end | ||||
| 	["remove(l::list)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(l) | ||||
| 			return table.remove(l.value) | ||||
| 		end | ||||
| 	}, | ||||
| 	["remove(l::list, i::number)"] = { | ||||
| 		mode = "untyped raw", | ||||
| 		value = function(l, i) | ||||
| 			return table.remove(l.value, i.value) | ||||
| 		end | ||||
| 	}, | ||||
| 	["find(l::list, v)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(l, v) | ||||
| 			local lv = l.type == "type" and l.value[1] or l | ||||
| 			for i, x in ipairs(lv.value) do | ||||
| 				if compare(x, v) then | ||||
| 					return i | ||||
| 				end | ||||
| 				return 0 | ||||
| 			end | ||||
| 		}, | ||||
| 			return { type = "number", value = 0 } | ||||
| 		end | ||||
| 	}, | ||||
| 	-- other methods | ||||
| 	rand = { | ||||
| 		{ | ||||
| 			arity = 0, return_type = "number", | ||||
| 			value = function() | ||||
| 				return math.random() | ||||
| 	["error(m::string)"] = function(m) error(m, 0) end, | ||||
| 	["rand"] = function() return math.random() end, | ||||
| 	["rand(a::number)"] = function(a) return math.random(a) end, | ||||
| 	["rand(a::number, b::number)"] = function(a, b) return math.random(a, b) end, | ||||
| 	["raw(v)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(v) | ||||
| 			if v.type == "type" then | ||||
| 				return v.value[1] | ||||
| 			else | ||||
| 				return v | ||||
| 			end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 1, types = { "number" }, return_type = "number", | ||||
| 			value = function(a) | ||||
| 				return math.random(a) | ||||
| 			end | ||||
| 		}, | ||||
| 		{ | ||||
| 			arity = 2, types = { "number", "number" }, return_type = "number", | ||||
| 			value = function(a, b) | ||||
| 				return math.random(a, b) | ||||
| 			end | ||||
| 		} | ||||
| 		end | ||||
| 	}, | ||||
| 	cycle = function(...) | ||||
| 		local l = {...} | ||||
| 	["type(v)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(v) | ||||
| 			if v.type == "type" then | ||||
| 				return v.value[2] | ||||
| 			else | ||||
| 				return { | ||||
| 					type = "string", | ||||
| 					value = v.type | ||||
| 				} | ||||
| 			end | ||||
| 		end | ||||
| 	}, | ||||
| 	["is of type(v, t)"] = { | ||||
| 		mode = "raw", | ||||
| 		value = function(v, t) | ||||
| 			return { | ||||
| 				type = "number", | ||||
| 				value = is_of_type(v, t) or 0 | ||||
| 			} | ||||
| 		end | ||||
| 	}, | ||||
| 	["cycle(l...)"] = function(l) | ||||
| 		local f, fseen = l[1], assert(anselme.running:eval(l[1]..".👁️", anselme.running:current_namespace())) | ||||
| 		for j=2, #l do | ||||
| 			local seen = assert(anselme.running:eval(l[j]..".👁️", anselme.running:current_namespace())) | ||||
|  | @ -426,12 +227,10 @@ functions = { | |||
| 		end | ||||
| 		return anselme.running:run(f, anselme.running:current_namespace()) | ||||
| 	end, | ||||
| 	random = function(...) | ||||
| 		local l = {...} | ||||
| 	["random(l...)"] = function(l) | ||||
| 		return anselme.running:run(l[math.random(1, #l)], anselme.running:current_namespace()) | ||||
| 	end, | ||||
| 	next = function(...) | ||||
| 		local l = {...} | ||||
| 	["next(l...)"] = function(l) | ||||
| 		local f = l[#l] | ||||
| 		for j=1, #l-1 do | ||||
| 			local seen = assert(anselme.running:eval(l[j]..".👁️", anselme.running:current_namespace())) | ||||
|  | @ -444,13 +243,7 @@ functions = { | |||
| 	end | ||||
| } | ||||
| 
 | ||||
| numeric_index = functions["("][1] | ||||
| string_index = functions["("][2] | ||||
| 
 | ||||
| package.loaded[...] = functions | ||||
| truthy = require((...):gsub("stdlib%.functions$", "interpreter.common")).truthy | ||||
| eval = require((...):gsub("stdlib%.functions$", "interpreter.expression")) | ||||
| find_function_variant = require((...):gsub("stdlib%.functions$", "parser.common")).find_function_variant | ||||
| local common = require((...):gsub("stdlib%.functions$", "interpreter.common")) | ||||
| truthy, compare, is_of_type = common.truthy, common.compare, common.is_of_type | ||||
| anselme = require((...):gsub("stdlib%.functions$", "anselme")) | ||||
| 
 | ||||
| return functions | ||||
|  |  | |||
|  | @ -130,6 +130,20 @@ types.anselme = { | |||
| 			if not v and ve then return v, ve end | ||||
| 			return { [k] = v } | ||||
| 		end | ||||
| 	}, | ||||
| 	type = { | ||||
| 		format = function(val) | ||||
| 			local k, ke = format(val[1]) | ||||
| 			if not k then return k, ke end | ||||
| 			local v, ve = format(val[2]) | ||||
| 			if not v then return v, ve end | ||||
| 			return ("%s::%s"):format(k, v) | ||||
| 		end, | ||||
| 		to_lua = function(val) | ||||
| 			local k, ke = to_lua(val[1]) | ||||
| 			if not k and ke then return k, ke end | ||||
| 			return k | ||||
| 		end | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue