Re: Self Modifying Code

new topic     » goto parent     » topic index » view thread      » older message » newer message
irv said...
lgregg said...

Is there a way to write self-modifying code in Euphoria? Or, perhaps, more simply, to have a Euphoria program write Euphoria code to an external file and then later "include" it in the same program?

Have you looked at the Preprocessor ?

It's not something I've used, but might work for your requirement.

Due to the parsing order (I'm guessing) Euphoria tries to read all the includes first, before running any code, so the following sort of thing will not work:

atom fn = open("time.e","w") 
puts(fn,sprintf("atom clock=%d",time())) 
close(fn) 
 
include time.e 
? clock 

<0052>:: can't find 'time.e' in any of ... 
    /home/irv 
    /home/irv/inc.ex 
    /home/irv/demos 
    /usr/local/include 
 
include time.e 
              ^ 

There's always the possibility of having your code write a (modified) copy of itself, then run that copy, I suppose.

It all depends upon what you are trying to do. Need more details - for example, EuGTK can certainly modify a program's appearance on the fly - button labels, colors, text, visibility of controls, etc. thru the use of simple .ini files, which can be written and loaded at any point, not just on startup.

It seems like so much of the World Wide Web is built with php, using embedded php code in html documents. For example:

<!DOCTYPE html> 
<html> 
<body> 
 
<?php 
$txt = "Hello world!"; 
$x = 5; 
$y = 10.5; 
 
echo $txt; 
echo "<br>"; 
echo $x; 
echo "<br>"; 
echo $y; 
?> 
 
</body> 
</html> 

BUT, why could we not do something similar using Euphoria?

<!DOCTYPE html> 
<html> 
<body> 
 
<?euphoria 
sequence txt = "Hello world!" 
integer x = 5 
atom y = 10.5 
 
printf(1,"txt=%s\n",{txt}) 
printf(1,"x=%g\n",x) 
printf(1,"y=%g\n",y) 
?> 
 
</body> 
</html> 

I wrote a preprocessor using an example from the OpenEuphoria site, to extract the Euphoria code and execute it. At this time, it does not return an html document with the embedded Euphoria code replaced with the results of running the preprocessor, although I imagine that is possible. I thought that Self Modifying code might be helpful. Here is the preprocessor:

/* 
Program:  process_file_eup.ex 
Date:  19-JAN-2019 
Purpose: To read a file and process one line at at time, pulling 
			out Euphoria (or other) code and writing to a file. 
			Blank lines are not output. 
			Should be able to use as a Euphoria pre-processor. 
Invocation: eui process_file_eup.ex i text_file o code_file 
				or as a preprocessor 
				eui extension:process_file_eup.ex {filename.extension (as shown earlier)} 
				e. g. 
				eui html:process_file_eup.ex eup_test_2.html 
 
*/ 
public include std/cmdline.e 
public include std/io.e 
public include std/sequence.e 
public include std/text.e 
 
 
constant begin_tag = lower("<?euphoria") -- change for other start tag 
		 , begin_tag_len = length(begin_tag) 
		 , end_tag = "?>" -- change for other stop tag 
		 , end_tag_len = length(end_tag) 
 
integer start = 0, stop  = 0 
sequence NULL = "" 
 
-- Process each supplied line. 
function process_each_line(sequence aLine, integer line_no, object data) 
	sequence lp=NULL 
	integer beginpos=0, endpos=0, done=0 
--		printf(data[1],"aLine=%s, start=%g\n",{aLine}&start) 
 
	loop do 
		if start = 0 then 
			beginpos = match(begin_tag, lower(aLine)) 
			if beginpos > 0 then 
				start = 1 
				aLine = aLine[beginpos + begin_tag_len .. $] 
			end if 
		end if 
		 
		if start = 1 then 
			endpos = match(end_tag, aLine) 
			if endpos > 0 then 
				stop = 1 
				lp = aLine[endpos + end_tag_len .. $] 
				aLine = aLine[1 .. endpos - 1] 
			end if 
		end if 
 
		if start = 1 and length(aLine) > 0 then 
			printf(data[1],"%s\n",{aLine}) 
		end if 
		 
		if stop = 1 then 
			start = 0 
			stop = 0 
		end if 
		 
		if length(lp) > 0 then 
			aLine = lp 
			lp = NULL 
		else 
			done = 1 
		end if 
			 
		until done=1 
	end loop 
 
	if data[2] > 0 and line_no = data[2] then 
		return 1 
	else 
		return 0 
  end if 
end function 
 
 
-- Main 
procedure main() 
integer in1, out1 
sequence cmd, extras 
 
cmd = command_line() 
if length(cmd) > 6 then 
	extras = cmd[7] 
else extras = {} 
end if 
 
--  Get input file 
if length(cmd) < 4 
	or compare(upper(cmd[4]),"STDIN") = 0 
then in1 = STDIN  
else 
	in1 = open(cmd[4],"r") 
	if in1 = -1 then  
		printf(1,"Could not open input file, %s, aborting\n",{cmd[4]}) 
		abort (11) 
	end if 
end if 
 
--  Get output file 
if length(cmd) < 6 
	or compare(upper(cmd[6]),"STDOUT") = 0 
then out1 = STDOUT  
else 
	out1 = open(cmd[6],"w") 
	if out1 = -1 then 
		printf(1,"Could not open ouput file, %s, aborting\n",{cmd[6]}) 
		abort (12) 
	end if 
end if 
 
--  The first element of the third argument is the output file handle 
process_lines(in1, routine_id("process_each_line"), {out1, 0}) 
 
close(in1) 
close(out1) 
 
end procedure 
main() 
 

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu