############################################################################
#
#	File:     exprfile.icn
#
#	Subject:  Procedures to produce programs on the fly
#
#	Author:   Ralph E. Griswold
#
#	Date:     August 5, 1997
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#	exprfile(exp, link, ...)
#			produces a pipe to a program that writes all the
#			results generated by exp.  The trailing arguments
#			name link files needed for the expression.
#
#			exprfile() closes any previous pipe it opened
#			and deletes its temporary file.  Therefore,
#			exprfile() cannot be used for multiple expression
#			pipes.
#
#			If the expression fails to compile, the global
#			expr_error is set to 1; otherwise 0.
#
#	exec_expr(expr_list, links[])
#			generates the results of executing the expression
#			contained in the lists expr_list with the specified
#			links.
#
#	plst2pstr(L)	converts the list of Icon programs lines in L to a
#			string with separating newlines.
#
#	pstr2plst(s)	converts the string of Icon program lines (separated
#			by newlines) to a list of lines.
#
#	ucode(file)	produces a ucode file from the Icon program in file.
#
############################################################################
#
#  Requires:  system(), pipes, /tmp
#
############################################################################
#
#  Links:  io
#
############################################################################

link io

global expr_error

procedure exprfile(exp, links[])	#: pipe for Icon expression
   local output
   static name, input

   expr_error := &null

   remove(\name)			# remove former executable
   close(\input)			# and close last pipe

   output := tempfile("expr", ".icn", "/tmp")

   image(output) ? {
      ="file("
      name := tab(find(".icn"))
      }

   write(output, "invocable all")
   every write(output, "link ", image(!links)) 
   write(output, "procedure main(args)")
   write(output, "   every write(", exp, ")")
   write(output, "end")

   close(output)

   if system("icont -o " || name || " -s " || name ||
      " >/dev/null 2>/dev/null") ~= 0 then {
          expr_error := 1
          remove(name || ".icn")
          fail
          }

   remove(name || ".icn")		# remove source code file

   #  Return a pipe for the executable.  Error messages are discarded.

   return input := open(name || " 2>/dev/null", "p")
   
end

procedure exec_expr(expr_list, links[])	#: execute expression in lists

   suspend !(exprfile ! push(links, plst2pstr(expr_list)))

end

procedure plst2pstr(L)			#: convert program list to string
   local result

   result := ""

   every result ||:= !L || "\n"

   return result

end

procedure pstr2plst(s)			#: convert program string to list
   local result

   result := []

   s ? {
      while put(result, tab(upto('\n'))) do
         move(1)
      if not pos(0) then put(result, tab(0))
      }

   return result

end

procedure ucode(file)			#: create ucode file

   if system("icont -s -c " || file) ~= 0 then fail

   return

end
