Re: geant: notion of local variables

Jocelyn <[email protected]> Fri, 01 Feb 2008 20:56:54 +0100
Newsgroups gmane.comp.lang.eiffel.gobo.general
Message-ID <[email protected]>
Hi,

Here is a potential patch to add local variable support to geant.

Any comment ?

Jocelyn

On 1/31/2008 18:33 PM, Jocelyn wrote:
> Hi Gobo team
>
> Would this make sense to have "local" variables in geant scripts ?
> I think it would be nice, it would allow to make nicer scripts.
>
> I was wondering, anyone knows if this would be easy (and good idea) to 
> introduce such "local" variable ?
>
> we could add  <setlocal  name="varname" value="val" /> and <unsetlocal 
> name="varname" />
> (maybe unsetlocal does not make sense .. since it is "local")
> pretty similar to <set .../> and <unset .../>
>
> I think this could be achieve without too much trouble, but I also 
> know the inside of geant might be tricky related to variable, 
> arguments, and so on ...
>
> Any comment ?
> Jocelyn
>
>
>
>
>


  ----------

Index: command/geant_available_command.e
===================================================================
--- command/geant_available_command.e	(revision 6284)
+++ command/geant_available_command.e	(working copy)
@@ -47,6 +47,9 @@
 	variable_name: STRING
 			-- Name of variable to set
 
+	local_variable_name: STRING
+			-- Name of local variable to set
+
 	true_value: STRING
 			-- Value to be set for variable named `variable_name'
 			-- in case `execute' evaluate a value of `True'
@@ -78,6 +81,17 @@
 			variable_name_set: variable_name = a_variable_name
 		end
 
+	set_local_variable_name (a_variable_name: like local_variable_name) is
+			-- Set `variable_name' to `a_variable_name'.
+		require
+			a_variable_name_not_void : a_variable_name /= Void
+			a_variable_name_not_empty: a_variable_name.count > 0
+		do
+			local_variable_name := a_variable_name
+		ensure
+			local_variable_name_set: local_variable_name = a_variable_name
+		end
+
 	set_true_value (a_true_value: like true_value) is
 			-- Set `true_value' to `a_true_value'.
 		require
@@ -106,15 +120,23 @@
 			-- Execute command.
 		local
 			a_from_file: STRING
+			v: STRING
 		do
 			check is_file_executable: is_file_executable end
 			a_from_file := file_system.pathname_from_file_system (resource_name, unix_file_system)
 
 			if file_system.file_exists (a_from_file) or else file_system.directory_exists (a_from_file) then
-				project.variables.set_variable_value (variable_name, true_value)
+				v := true_value
 			else
-				project.variables.set_variable_value (variable_name, false_value)
+				v := false_value
 			end
+
+			if variable_name /= Void then
+				project.variables.set_variable_value (variable_name, v)
+			end
+			if local_variable_name /= Void then
+				project.current_target_locals.set_variable_value (local_variable_name, v)
+			end
 		end
 
 end
Index: command/geant_exec_command.e
===================================================================
--- command/geant_exec_command.e	(revision 6284)
+++ command/geant_exec_command.e	(working copy)
@@ -149,6 +149,7 @@
 				if exit_code = 0 then
 					create a_string_interpreter.make
 					Project_variables_resolver.set_variables (project.variables)
+					Project_variables_resolver.set_local_variables (project.current_target_locals)
 					a_string_interpreter.set_variable_resolver (Project_variables_resolver)
 
 					fileset.execute
Index: command/geant_set_command.e
===================================================================
--- command/geant_set_command.e	(revision 6284)
+++ command/geant_set_command.e	(working copy)
@@ -69,6 +69,13 @@
 			-- Put variable in project variables pool.
 		do
 			project.trace (<<"  [set] ", name, "=", value>>)
+			if project.current_target.formal_arguments /= Void and then project.current_target.formal_arguments.has (name) then
+				project.log (<<"  [set] warning: conflict with argument variable %"", name, "%"">>)
+			end
+			if project.current_target_locals /= Void and then project.current_target_locals.has (name) then
+				project.log (<<"  [set] warning: conflict with local variable %"", name, "%"">>)
+			end
+
 			project.variables.set_variable_value (name, value)
 			exit_code := 0
 		end
Index: command/geant_setlocal_command.e
===================================================================
--- command/geant_setlocal_command.e	(revision 0)
+++ command/geant_setlocal_command.e	(revision 0)
@@ -0,0 +1,81 @@
+indexing
+
+	description:
+
+		"Setlocal commands"
+
+	library: "Gobo Eiffel Ant"
+	copyright: "Copyright (c) 2001, Sven Ehrke and others"
+	license: "MIT License"
+	date: "$Date$"
+	revision: "$Revision$"
+
+class GEANT_SETLOCAL_COMMAND
+
+inherit
+
+	GEANT_COMMAND
+
+create
+
+	make
+
+feature -- Status report
+
+	is_executable : BOOLEAN is
+			-- Can command be executed?
+		do
+			Result := (name /= Void and then name.count > 0) and value /= Void
+		ensure then
+			name_not_void: Result implies name /= Void
+			name_not_empty: Result implies name.count > 0
+			value_not_void: Result implies value /= Void
+		end
+
+feature -- Access
+
+	name: STRING
+			-- Name of environment variable
+
+	value: STRING
+			-- Value of environment variable
+
+feature -- Setting
+
+	set_name (a_name: like name) is
+			-- Set `name' to `a_name'.
+		require
+			a_name_not_void: a_name /= Void
+			a_name_not_empty: a_name.count > 0
+		do
+			name := a_name
+		ensure
+			name_set: name = a_name
+		end
+
+	set_value (a_value: like value) is
+			-- Set `value' to `a_value'.
+		require
+			a_value_not_void: a_value /= Void
+		do
+			value := a_value
+		ensure
+			value_set: value = a_value
+		end
+
+feature -- Execution
+
+	execute is
+			-- Put variable in project variables pool.
+		do
+			project.trace (<<"  [setlocal] ", name, "=", value>>)
+			if project.current_target.formal_arguments /= Void and then project.current_target.formal_arguments.has (name) then
+				project.log (<<"  [set] warning: conflict with argument variable %"", name, "%"">>)
+			end
+
+			check current_locals_not_void: project.current_target_locals /= Void end
+			project.current_target_locals.set_variable_value (name, value)
+			exit_code := 0
+		end
+
+end

Property changes on: command\geant_setlocal_command.e
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Index: geant_project.e
===================================================================
--- geant_project.e	(revision 6284)
+++ geant_project.e	(working copy)
@@ -54,6 +54,8 @@
 			create a_tester
 			selected_targets.set_key_equality_tester (a_tester)
 
+			create {DS_ARRAYED_STACK [GEANT_TARGET]} targets_stack.make (10)
+
 			build_successful := True
 		ensure
 			variables_set: a_variables /= Void implies variables = a_variables
@@ -448,7 +450,9 @@
 				else
 					a_execute_target := a_target
 				end
-				current_target := a_execute_target
+
+				targets_stack.force (a_execute_target)
+				check current_target = a_execute_target end
 				if a_execute_target.project /= Current then
 					a_execute_target.project.execute_target (a_execute_target, a_arguments, a_force, a_polymorph)
 				else
@@ -456,9 +460,9 @@
 					a_execute_target.execute
 					target_arguments_stack.remove
 				end
+				targets_stack.remove
 			end
-
-			current_target := old_current_target
+			check current_target = old_current_target end
 		end
 
 feature -- Output
@@ -540,10 +544,49 @@
 
 feature {GEANT_COMMAND} -- Access GEANT_COMMAND
 
-	current_target: GEANT_TARGET
+	targets_stack: DS_STACK [GEANT_TARGET]
+			-- Stack of targets
+
+	current_target: GEANT_TARGET is
 			-- Currently executing target;
 			-- Set during processing `execute_target'
+		do
+			if not targets_stack.is_empty then
+				Result := targets_stack.item
+			end
+		end
 
+feature {GEANT_COMMAND, GEANT_INTERPRETING_ELEMENT} -- Access GEANT_INTERPRETING_ELEMENT		
+
+	current_target_locals: GEANT_VARIABLES is
+			-- Locals of `current_target'
+		local
+			c: like current_target
+		do
+			c := current_target
+			if c /= Void then
+				Result := c.locals
+			end
+		end
+
+	caller_target_locals: GEANT_VARIABLES is
+			-- Locals of caller target
+		local
+			p, c: like current_target
+		do
+			if not targets_stack.is_empty then
+				c := targets_stack.item
+				targets_stack.remove
+				if not targets_stack.is_empty then
+					p := targets_stack.item
+					if p /= Void then
+						Result := p.locals
+					end
+				end
+				targets_stack.force (c)
+			end
+		end
+
 invariant
 
 	name_not_void: name /= Void
Index: geant_project_variable_resolver.e
===================================================================
--- geant_project_variable_resolver.e	(revision 6284)
+++ geant_project_variable_resolver.e	(working copy)
@@ -63,6 +63,14 @@
 				end
 			end
 
+			if Result = Void then --and local_variables /= Void then
+					-- Search local variables:
+				local_variables.search (a_name)
+				if local_variables.found then
+					Result := local_variables.found_item
+				end
+			end
+
 			if Result = Void then
 					-- Search project variables:
 				variables.search (a_name)
@@ -133,6 +141,9 @@
 	variables: GEANT_VARIABLES
 			-- Variables used for resolving
 
+	local_variables: GEANT_VARIABLES
+			-- Local variables used for resolving
+
 feature -- Status report
 
 	has (a_name: STRING): BOOLEAN is
@@ -159,6 +170,12 @@
 				Result := Commandline_variables.found
 			end
 
+			if not Result then --and local_variables /= Void then
+					-- Search local project variables:
+				local_variables.search (a_name)
+				Result := local_variables.found
+			end
+
 			if not Result then
 					-- Search project variables:
 				variables.search (a_name)
@@ -184,4 +201,12 @@
 			variables_set: variables = a_variables
 		end
 
+	set_local_variables (a_variables: like local_variables) is
+			-- Set `local_variables' to `a_variables'.
+		do
+			local_variables := a_variables
+		ensure
+			local_variables_set: local_variables = a_variables
+		end
+
 end
Index: geant_project_variables.e
===================================================================
--- geant_project_variables.e	(revision 6284)
+++ geant_project_variables.e	(working copy)
@@ -39,9 +39,11 @@
 			a_name: STRING
 			a_value: STRING
 		do
-			precursor
+			Precursor
 				-- Create built-in variables $GOBO_OS, $is_windows/$is_unix, $exe
 			Project_variables_resolver.set_variables (Current)
+			Project_variables_resolver.set_local_variables (Void)
+
 			a_name := gobo_os_name
 			if not Project_variables_resolver.has (a_name) then
 				set_variable_value (a_name, Default_builtin_variables.value (a_name))
Index: geant_shared_properties.e
===================================================================
--- geant_shared_properties.e	(revision 6284)
+++ geant_shared_properties.e	(working copy)
@@ -33,8 +33,8 @@
 
 	KL_SHARED_FILE_SYSTEM
 		export {NONE} all end
-		
 
+
 feature -- Access
 
 	Commandline_variables: GEANT_VARIABLES is
@@ -142,7 +142,7 @@
 --			a_parent_project: GEANT_PROJECT
 --		do
 --			from
---				i := 1 
+--				i := 1
 --			until
 --				i > system_parents.count or else Result
 --			loop
@@ -171,7 +171,7 @@
 --			a_parent_project: GEANT_PROJECT
 --		do
 --			from
---				i := 1 
+--				i := 1
 --			until
 --				i > system_parents.count or else Result
 --			loop
@@ -270,7 +270,7 @@
 						nice_string := False
 					end
 				end
-	
+
 				if s.count > 0 then
 					if s.item (s.count) = a_delimiter then
 						s.keep_head (s.count - 1)
Index: geant_target.e
===================================================================
--- geant_target.e	(revision 6284)
+++ geant_target.e	(working copy)
@@ -105,6 +105,7 @@
 				end
 			end
 
+			create locals.make
 		end
 
 feature -- Access
@@ -244,6 +245,9 @@
 			end
 		end
 
+	locals: GEANT_VARIABLES
+			-- Local variables of Current target
+
 feature -- Status report
 
 	is_executed: BOOLEAN
@@ -493,6 +497,7 @@
 					if xml_element.has_attribute_by_name (Dir_attribute_name) then
 						create a_string_interpreter.make
 						Project_variables_resolver.set_variables (project.variables)
+						Project_variables_resolver.set_local_variables (project.caller_target_locals)
 						a_string_interpreter.set_variable_resolver (Project_variables_resolver)
 						a_new_target_cwd := a_string_interpreter.interpreted_string (
 							xml_element.attribute_by_name (Dir_attribute_name).value.out)
@@ -514,6 +519,9 @@
 					a_arguments := prepared_arguments_from_formal_arguments (a_arguments)
 					target_arguments_stack.force (a_arguments)
 
+						-- Prepare locals:
+					create locals.make
+
 						-- Execute nested tasks:
 					cs := xml_element.new_cursor
 					from
@@ -609,6 +617,9 @@
 			elseif STRING_.same_string (a_xml_element.name, Setenv_task_name) then
 					-- setenv
 				create {GEANT_SETENV_TASK} a_task.make (project, a_xml_element)
+			elseif STRING_.same_string (a_xml_element.name, Setlocal_task_name) then
+					-- setlocal
+				create {GEANT_SETLOCAL_TASK} a_task.make (project, a_xml_element)
 			elseif STRING_.same_string (a_xml_element.name, Xslt_task_name) then
 					-- xslt
 				create {GEANT_XSLT_TASK} a_task.make (project, a_xml_element)
Index: parser/geant_element_names.e
===================================================================
--- parser/geant_element_names.e	(revision 6284)
+++ parser/geant_element_names.e	(working copy)
@@ -214,6 +214,15 @@
 			task_name_not_empty: Result.count > 0
 		end
 
+	Setlocal_task_name: STRING is
+			-- "setlocal" task name
+		once
+			Result := "setlocal"
+		ensure
+			task_name_not_void: Result /= Void
+			task_name_not_empty: Result.count > 0
+		end
+
 	Xslt_task_name: STRING is
 			-- "xslt" task name
 		once
Index: parser/geant_interpreting_element.e
===================================================================
--- parser/geant_interpreting_element.e	(revision 6284)
+++ parser/geant_interpreting_element.e	(working copy)
@@ -67,6 +67,8 @@
 		do
 				-- TODO: improve efficiency:
 			Project_variables_resolver.set_variables (project.variables)
+			Project_variables_resolver.set_local_variables (project.current_target_locals)
+
 				-- Set default execution conditions:
 			if_condition := true
 			unless_condition := false
@@ -104,22 +106,14 @@
 			-- Value of attribue `an_attr_name'
 		local
 			a_string_interpreter: GEANT_STRING_INTERPRETER
-			a_variable_resolver: GEANT_VARIABLES_VARIABLE_RESOLVER
 		do
 			Result := xml_element.attribute_by_name (an_attr_name).value
 			if Result.count > 0 then
 				create a_string_interpreter.make
-					-- Search variable in arguments if any (TODO: make this more efficient)
-					-- (NOTE: checking that the stack is not empty is only needed for GEANT startup):
-				if target_arguments_stack.count > 0 then
-					create a_variable_resolver.make
-					a_string_interpreter.set_variable_resolver (a_variable_resolver)
-					a_variable_resolver.set_variables (target_arguments_stack.item)
-					Result := a_string_interpreter.interpreted_string (Result)
-				end
 
 					-- Search variable in project variables:
 				Project_variables_resolver.set_variables (project.variables)
+				Project_variables_resolver.set_local_variables (project.current_target_locals)
 				a_string_interpreter.set_variable_resolver (Project_variables_resolver)
 				Result := a_string_interpreter.interpreted_string (Result)
 			end
Index: task/geant_available_task.e
===================================================================
--- task/geant_available_task.e	(revision 6284)
+++ task/geant_available_task.e	(working copy)
@@ -62,6 +62,12 @@
 					command.set_variable_name (a_value)
 				end
 			end
+			if has_attribute (Local_variable_attribute_name) then
+				a_value := attribute_value (Local_variable_attribute_name)
+				if a_value.count > 0 then
+					command.set_local_variable_name (a_value)
+				end
+			end
 		end
 
 feature -- Access
@@ -89,6 +95,15 @@
 			atribute_name_not_empty: Result.count > 0
 		end
 
+	Local_variable_attribute_name: STRING is
+			-- Name of xml attribute for local_variable
+		once
+			Result := "local_variable"
+		ensure
+			attribute_name_not_void: Result /= Void
+			atribute_name_not_empty: Result.count > 0
+		end
+
 	True_value_attribute_name: STRING is
 			-- Name of xml attribute for true_value
 		once
Index: task/geant_setlocal_task.e
===================================================================
--- task/geant_setlocal_task.e	(revision 0)
+++ task/geant_setlocal_task.e	(revision 0)
@@ -0,0 +1,76 @@
+indexing
+
+	description:
+
+		"Setlocal tasks"
+
+	library: "Gobo Eiffel Ant"
+	copyright: "Copyright (c) 2001, Sven Ehrke and others"
+	license: "MIT License"
+	date: "$Date$"
+	revision: "$Revision$"
+
+class GEANT_SETLOCAL_TASK
+
+inherit
+
+	GEANT_TASK
+		rename
+			make as task_make
+		redefine
+			command
+		end
+
+create
+
+	make
+
+feature {NONE} -- Initialization
+
+	make (a_project: GEANT_PROJECT; an_xml_element: XM_ELEMENT) is
+			-- Create a new task with information held in `an_element'.
+		local
+			a_value: STRING
+		do
+			create command.make (a_project)
+			task_make (command, an_xml_element)
+				-- name:
+			if has_attribute (Name_attribute_name) then
+				a_value := attribute_value (Name_attribute_name)
+				if a_value.count > 0 then
+					command.set_name (a_value)
+				end
+			end
+				-- value:
+			if has_attribute (Value_attribute_name) then
+				a_value := attribute_value (Value_attribute_name)
+				command.set_value (a_value)
+			end
+		end
+
+feature -- Access
+
+	command: GEANT_SETLOCAL_COMMAND
+			-- Setenv commands
+
+feature {NONE} -- Constants
+
+	Name_attribute_name: STRING is
+			-- "name" attribute name
+		once
+			Result := "name"
+		ensure
+			attribute_name_not_void: Result /= Void
+			attribute_name_not_empty: Result.count > 0
+		end
+
+	Value_attribute_name: STRING is
+			-- Name of xml attribute for value
+		once
+			Result := "value"
+		ensure
+			attribute_name_not_void: Result /= Void
+			atribute_name_not_empty: Result.count > 0
+		end
+
+end

Property changes on: task\geant_setlocal_task.e
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native



[Non-text portions of this message have been removed]