mirror of
				https://github.com/Reuh/anselme.git
				synced 2025-10-27 16:49:31 +00:00 
			
		
		
		
	Variable must now be explicitly marked as persistent
This commit is contained in:
		
							parent
							
								
									e9606cdee0
								
							
						
					
					
						commit
						2c6d66c222
					
				
					 11 changed files with 384 additions and 106 deletions
				
			
		|  | @ -66,7 +66,7 @@ common = { | |||
| 	-- returns depth, or math.huge if no constraint | ||||
| 	-- returns nil, err | ||||
| 	check_constraint = function(state, fqm, val) | ||||
| 		local constraint = state.variable_constraints[fqm] | ||||
| 		local constraint = state.variable_metadata[fqm].constraint | ||||
| 		if constraint then | ||||
| 			if not constraint.value then | ||||
| 				local v, e = eval(state, constraint.pending) | ||||
|  | @ -87,7 +87,7 @@ common = { | |||
| 	-- returns true | ||||
| 	-- returns nil, mutation illegal message | ||||
| 	check_mutable = function(state, fqm) | ||||
| 		if state.variable_constants[fqm] then | ||||
| 		if state.variable_metadata[fqm].constant then | ||||
| 			return nil, ("can't change the value of a constant %q"):format(fqm) | ||||
| 		end | ||||
| 		return true | ||||
|  | @ -114,12 +114,12 @@ common = { | |||
| 				return nil, ("%s; while evaluating default value for variable %q defined at %s"):format(e, fqm, var.value.source) | ||||
| 			end | ||||
| 			-- make constant if variable is constant | ||||
| 			if state.variable_constants[fqm] then | ||||
| 			if state.variable_metadata[fqm].constant then | ||||
| 				v = copy(v) | ||||
| 				common.mark_constant(v) | ||||
| 			end | ||||
| 			-- set variable | ||||
| 			local s, err = common.set_variable(state, fqm, v, state.variable_constants[fqm]) | ||||
| 			local s, err = common.set_variable(state, fqm, v, state.variable_metadata[fqm].constant) | ||||
| 			if not s then return nil, err end | ||||
| 			return v | ||||
| 		else | ||||
|  | @ -218,9 +218,10 @@ common = { | |||
| 		table.insert(modified, v) | ||||
| 	end, | ||||
| 	--- returns true if a variable should be persisted on save | ||||
| 	-- will exclude: undefined variables, variables in scoped functions, constants, internal anselme variables | ||||
| 	-- will exclude: variable that have not been evaluated yet and non-persistent variable | ||||
| 	-- this will by consequence excludes variable in scoped variables (can be neither persistent not evaluated into global state), constants (can not be persistent), internal anselme variables (not marked persistent), etc. | ||||
| 	should_keep_variable = function(state, name, value) | ||||
| 		return value.type ~= "undefined argument" and value.type ~= "pending definition" and name:match("^"..identifier_pattern.."$") and not name:match("^anselme%.") and not state.variable_constants[name] | ||||
| 		return value.type ~= "pending definition" and state.variable_metadata[name].persistent | ||||
| 	end, | ||||
| 	--- check truthyness of an anselme value | ||||
| 	truthy = function(val) | ||||
|  |  | |||
|  | @ -309,7 +309,7 @@ local function eval(state, exp) | |||
| 							local depth, err = check_constraint(state, param.full_name, val) | ||||
| 							if not depth then | ||||
| 								ok = false | ||||
| 								local v = state.variable_constraints[param.full_name].value | ||||
| 								local v = state.variable_metadata[param.full_name].constraint.value | ||||
| 								table.insert(tried_function_error_messages, ("%s: argument %s is not of expected type %s"):format(fn.pretty_signature, param.name, format(v) or v)) | ||||
| 								break | ||||
| 							end | ||||
|  | @ -347,7 +347,7 @@ local function eval(state, exp) | |||
| 						local depth, err = check_constraint(state, param.full_name, assignment) | ||||
| 						if not depth then | ||||
| 							ok = false | ||||
| 							local v = state.variable_constraints[param.full_name].value | ||||
| 							local v = state.variable_metadata[param.full_name].constraint.value | ||||
| 							table.insert(tried_function_error_messages, ("%s: argument %s is not of expected type %s"):format(fn.pretty_signature, param.name, format(v) or v)) | ||||
| 						end | ||||
| 						depths.assignment = depth | ||||
|  | @ -418,8 +418,11 @@ local function eval(state, exp) | |||
| 					if not s then return nil, e end | ||||
| 				end | ||||
| 				-- get function vars | ||||
| 				local checkpoint, checkpointe = get_variable(state, fn.namespace.."🔖") | ||||
| 				if not checkpoint then return nil, checkpointe end | ||||
| 				local checkpoint, checkpointe | ||||
| 				if fn.resumable then | ||||
| 					checkpoint, checkpointe = get_variable(state, fn.namespace.."🔖") | ||||
| 					if not checkpoint then return nil, checkpointe end | ||||
| 				end | ||||
| 				local seen, seene = get_variable(state, fn.namespace.."👁️") | ||||
| 				if not seen then return nil, seene end | ||||
| 				-- execute lua functions | ||||
|  | @ -488,7 +491,7 @@ local function eval(state, exp) | |||
| 				else | ||||
| 					local e | ||||
| 					-- eval function from start | ||||
| 					if paren_call or checkpoint.type == "nil" then | ||||
| 					if paren_call or not fn.resumable or checkpoint.type == "nil" then | ||||
| 						ret, e = run(state, fn.child) | ||||
| 					-- resume at last checkpoint | ||||
| 					else | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ run_line = function(state, line) | |||
| 			value = reached.value + 1 | ||||
| 		}) | ||||
| 		if not s then return nil, e end | ||||
| 		s, e = set_variable(state, line.parent_function.namespace.."🔖", { | ||||
| 		s, e = set_variable(state, line.parent_resumable.namespace.."🔖", { | ||||
| 			type = "function reference", | ||||
| 			value = { line.name } | ||||
| 		}) | ||||
|  | @ -160,7 +160,7 @@ run_block = function(state, block, resume_from_there, i, j) | |||
| 		if not reached then return nil, reachede end | ||||
| 		local seen, seene = get_variable(state, parent_line.namespace.."👁️") | ||||
| 		if not seen then return nil, seene end | ||||
| 		local checkpoint, checkpointe = get_variable(state, parent_line.parent_function.namespace.."🔖") | ||||
| 		local checkpoint, checkpointe = get_variable(state, parent_line.parent_resumable.namespace.."🔖") | ||||
| 		if not checkpoint then return nil, checkpointe end | ||||
| 		local s, e = set_variable(state, parent_line.namespace.."👁️", { | ||||
| 			type = "number", | ||||
|  | @ -175,7 +175,7 @@ run_block = function(state, block, resume_from_there, i, j) | |||
| 		-- don't update checkpoint if an already more precise checkpoint is set | ||||
| 		-- (since we will go up the whole checkpoint hierarchy when resuming from a nested checkpoint) | ||||
| 		if checkpoint.type == "nil" or not checkpoint.value[1]:match("^"..escape(parent_line.name)) then | ||||
| 			s, e = set_variable(state, parent_line.parent_function.namespace.."🔖", { | ||||
| 			s, e = set_variable(state, parent_line.parent_resumable.namespace.."🔖", { | ||||
| 				type = "function reference", | ||||
| 				value = { parent_line.name } | ||||
| 			}) | ||||
|  | @ -184,11 +184,11 @@ run_block = function(state, block, resume_from_there, i, j) | |||
| 		merge_state(state) | ||||
| 	end | ||||
| 	-- go up hierarchy if asked to resume | ||||
| 	-- will stop at function boundary | ||||
| 	-- will stop at resumable function boundary | ||||
| 	-- if parent is a choice, will ignore choices that belong to the same block (like the whole block was executed naturally from a higher parent) | ||||
| 	-- if parent if a condition, will mark it as a success (skipping following else-conditions) (for the same reasons as for choices) | ||||
| 	-- if parent pushed a tag, will pop it (tags from parents are added to the stack in run()) | ||||
| 	if resume_from_there and block.parent_line and not block.parent_line.resume_boundary then | ||||
| 	if resume_from_there and block.parent_line and not block.parent_line.resumable then | ||||
| 		local parent_line = block.parent_line | ||||
| 		if parent_line.type == "choice" then | ||||
| 			state.interpreter.skip_choices_until_flush = true | ||||
|  | @ -212,9 +212,9 @@ local function run(state, block, resume_from_there, i, j) | |||
| 	local tags_len = tags:len(state) | ||||
| 	if resume_from_there then | ||||
| 		local tags_to_add = {} | ||||
| 		-- go up in hierarchy in ascending order until function boundary | ||||
| 		-- go up in hierarchy in ascending order until resumable function boundary | ||||
| 		local parent_line = block.parent_line | ||||
| 		while parent_line and not parent_line.resume_boundary do | ||||
| 		while parent_line and not parent_line.resumable do | ||||
| 			if parent_line.type == "tag" then | ||||
| 				local v, e = eval(state, parent_line.expression) | ||||
| 				if not v then return v, ("%s; at %s"):format(e, parent_line.source) end | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue