$define aa "}\nsuspend!{ile_exp:=\\|@ile_var}\n\\ile_exp|stop(\"# No results.\")\n(*ile_exp=0)&write(\"[]\")\nend"
$define zz "procedure main(x)\nevery write(image(z:=ile_main(create x[1]),if type(z)==\"list\"then main([z])else z))\nend\nprocedure ile_main(ile_var)\ninitial ile_var:=create{"
global d, v, n, q
procedure main( cc )
kk := 1
a := b := c := 0
vv := cc[ 1 ]
if type( vv ) == "file" then yy := 1 else { case vv of {
    ( "?" | "help" ) : { write( "Usage: lile [-e [file to edit]][-i <file to include>][-c]\nThe file to include is the name of a file containing Icon procedures ( not main() ).\nThe -e option by itself calls the editor program.  If a file to edit follows it, a\ncopy of it is edited, and will not be saved unless you use the save command.\nThe -c option evaluates C programs.  The options can be entered in any order.\nCommands:\n; : Begin a procedure declaration ( prompts for comments after a hash ).\n# : End a procedure declaration ( comments after this one will not be saved ).\n;0 : List the successfully evaluated expressions.\n;1 : Repeat the previous successful evaluation.\n;2 : Save the code that produced the previous successful evaluation to a file.\n;3 : Show this help.\n;4 : Cancel the successfully evaluated expressions.\n;5 : Cancel the unevaluated expressions entered so far.\n;6 : Show the procedures that have been declared.\n;7 : Call the editor program to edit the procedures.\n;8 : Save the procedures to a file.\n;9 : Exit the program.\nUsage notes:\n(1) Evaluation occurs only if the following two conditions are met:\n(1a) The last line entered contains a right bracket, which closes a list, and\n(1b) curly brackets and parenthesis have all been closed as well ( if opened ).\n(2) It is possible to override evaluation by adding a ';' at the end of the line.\n(3) Entering nothing at all removes the last expression entered.  Thereafter,\n(3a) a '<' indicates an unevaluated expression, '>' an evaluated one." ) 
	return }

    "-e" : { p := 1
	nn := cc[ 2 ]
	\nn == "-i" & ( xx := cc[ 3 ] )
	\cc[ 3 ] == "-i" & ( xx := cc[ 4 ] )
	bb := cc2( nn, p ) }
		
    "-i" : { xx := cc[ 2 ] 
	\cc[ 3 ] == "-e" & ( p := 1 )
	nn := cc[ 4 ]
	bb := cc2( nn, p ) }
	
    "-c" : { ( dd := \cc[ 2 ] ) | ( dd := [] )
	if type( dd ) == "list" then ( gg := open( "lice_main.c", "crw" ) | stop( "cannot create tmpfile" ) ) else
	    stop( "Enter lile ? for help." )
	( qq := \cc[ 3 ] ) | ( qq := [] )
	( uu := \cc[ 4 ] ) | ( uu := [] )
	( q := \cc[ 5 ] ) | ( q := 0 )
	( d := \cc[ 6 ] ) | ( d := 0 ) 
	( v := \cc[ 7 ] ) | ( v := 0 )
	( n := \cc[ 8 ] ) | ( n := 0 )
	p1 := yy := 1 }

    default : { \vv & stop( "Enter lile ? for help." ) 
 	bb := open( "ile_ile", "crw" ) | stop( "cannot create libfile" ) 
	}
    }    
    /p1 & { system( "clear" )
	write( "# lile, Linux Icon list evaluator: enter ;3 for help." ) } 
    }
/p1 & { pp := []
    ff := []
    m := []
    d := v := n := w := 0 }

repeat { /yy & {
    gg := open( "ile_main.icn", "crw" ) | stop( "cannot create tmpfile" )
    write( gg, "$include \"", \xx, "\"" )
    write( gg, zz ) }
    /p1 & { 
	dd := []
	qq := []
	uu := []
	q := l := 0 }

    repeat { case kk of { 0 : { case kk1 of {
	"5" : *qq > 0 & { m := m[ 1:-*dd ]
	    w := *m
	    dd := []
	    qq := []
	    uu := []
	    q := a := b := c := v := d := n := l := 0
	    system( "clear" )
	    ww( ff, "> " ) }

	"4" : *pp > 0 & { pp := []
	    m := m[ *ff + 1:0 ] 
	    w := *m
	    ff := [] }

	"6" : \p & { seek( bb, 1 )
	    while write( read( bb ) ) }

	"9" : { write( "Bye." )
	    break break }

	"8" : \p & { write( "Enter file name." )
	    ( rr := read() ) ~== "" & system( "cp ile_ile " || rr ) }

	"7" : { p := 1
	    system( "editor" || " ile_ile" ) }

	"3" : main( [ "help" ] )
	"0" : *ff > 0 & { system( "clear" )
	    ww( ff, "> " ) }

	"2" : *pp > 0 & { write( "Enter file name." )
	    ( ss := read() ) ~== "" & {
		mm := open( ss, "crw" )
		write( mm, "$include \"", \xx, "\"" )
		every write( mm, zz | !pp | aa )
		\p & { seek( bb, 1 )
		    while write( mm, read( bb ) ) }

		close( mm ) }
	    }
	"1" : *pp > 0 & { if \m2 then {
	    if m1 := ( 1 < m[ -1 ] ) then pp[ -m1 ] := "[" || pp[ -m1 ]
		else pp[ -1 ] := "[" || pp[ -1 ]
	    if pp[ -1 ][ -1 ] == ";" then pp[ -1 ][ -1 ] := "]" else pp[ -1 ] ||:= "]" }
	    every write( gg, !pp | aa )
	    \p & write( gg, "$include \"ile_ile\"" )
	    0 ~= system( "icont -s ile_main.icn -x" ) & ww( ff, "> " )
	    gg := open( "ile_main.icn", "crw" )
	    write( gg, "$include \"", \xx, "\"" )
	    write( gg, zz ) }
	}	    
	q > 0 & ( ee1 := 1 ) }
	1 : { /yy & q = 0 & writes( ": " )
	    tt := read()	
	    /p1 & case tt[ 1 ] of {
		";" : /yy & { if kk1 := \tt[ 2 ] then kk := 0 else kk := 2
		    next }

		"#" : \yy & { q > 0 & { writes( "# Failed to enclose expressions. Quit? ( y ): " )
		    if read() == "y" then return else { every ww( ff | put( dd, uu ) )
			next }
		    }
		    every ww( ff | dd, vv )
		    return }
		}
	    \p1 & tt == "" & { system( "clear" )
		p3( pull( qq ) )
		*uu = 0 & { if *dd = 0 then break break else { pull( dd )
		    ww( dd )
		    next } }
		
		uu := ee( 0, dd ||| uu, *dd )
		next }

    	    tt ? { x := y := z := 0
		f := f1 := &null
		while ll := move( 1 ) do { case ll of {
		    "[" : { z +:= 1; d +:= 1 }
		    "]" : { z -:= 1; d -:= 1; f := 1 }
		    "(" : { x +:= 1; v +:= 1 }
		    ")" : { x -:= 1; v -:= 1 }
		    "{" : { y +:= 1; n +:= 1 }
		    "}" : { y -:= 1; n -:= 1; f1 := 1 } } }
		}
    	    ( n | d | v ) < 0 & { d := a
		v := b
		n := c
		if \p1 then { system( "clear" )
		    ww( dd ) } else if \yy then { write( "# ", cc[ 2 ] )
			every ww( ff | dd ) } else { write( "# Failed to enclose expressions." )  
			ww( dd, "< " )		
			q > 0 & writes( ": " ) 
		    }
		ee( 0, uu ) 
		next }
	    
	    put( qq, tt )
	    if d = v = n = 0 then { 
		if q > 0 then { put( uu, tt )
		    put( dd, uu ) } else { tt == "" & { 
			if *qq = 1 then { qq := []
			    if w = 0 then { if /yy then { write( "Bye." )
				break break } else return } else { pp := pp[ 1:-pull( m ) ]
				w := *m
				pull( ff )
				if \yy then { write( "# ", cc[ 2 ] )
				    ww( ff ) } else { system( "clear" )
				    ww( ff, "> " ) }
				m2 := 1 }
			    } else { pull( qq )
			    qq := qq[ 1:-pull( m ) ]
			    w := *m
			    pull( dd )
			    if \yy then { write( "# ", cc[ 2 ] )
				every ww( ff | dd ) } else { if *dd = 0 then { system( "clear" )
				    ww( ff, "> " ) } else { *ff = 0 & system( "clear" )
				    ww( dd, "< " ) } 
				}
			    } 
			next }
		    put( dd, tt ) }

		/p1 & ( w := *put( m, l + 1 ) )
		if /f1 & \p1 then next else { /p1 & {
		    ( /f | ( tt[ -1 ] == ";" ) ) & {
			uu := []
			l := q := a := b := c := 0
			next }
		    } }
		if /yy then { every write( gg, !( pp | qq ) | aa )
		    \p & write( gg, "$include \"ile_ile\"" )
		    if 0 = system( "icont -s ile_main.icn -x" ) then { 
			pp |||:= qq
			ff |||:= dd } else { ww( ff, "> " )
			m := m[ 1:-*dd ] 
			w := *m }
		    } else { \p1 & { every write( gg, !qq ) 
			0 = system( "gcc -ansi -pedantic -Wall -O -o lice_main lice_main.c" ) &
			    system( "$PWD/lice_main" )
			writes( "Enter q to quit " )
			read() == "q" & break break
			pull( dd )
			system( "clear" )
			uu := ee( 0, dd ||| uu, *dd )
			q -:= 1
			p3( pull( qq ) )
			main( [ "-c", dd, qq, uu, q, d, v, n ] ) 
			break break }
			
		    ff |||:= dd
		    pp |||:= qq }
		    
		a := b := c := 0
		break } else { a := d
		b := v
		c := n }

	    put( uu, tt ) 
	    /p1 & ( l +:= 1 )
	    if ( x | y | z ) > 0 then ee( q +:= 1, uu ) else
		if ( x | y | z ) < 0 then { if ( q -:= 1 ) = 0 then q := 1
		    ee( q, uu ) } else ee( q, uu )
	    next }

	2 : { p := 1
	    seek( bb, 0 )
	    writes( "# " )
	    write( bb, "# ", bb1 := read() )
	    d1 := d
	    v1 := v
	    n1 := n
	    q1 := q
	    main( [ bb, bb1 ] )
	    q := q1
	    n := n1
	    v := v1
	    d := d1
	    q > 0 & ( ee1 := 1 )
	    kk1 := "" }
	}
	*ff = 0 & kk1 ~== "3" & kk1 ~== "6" & system( "clear" )
	ww( dd, "< " )
	\ee1 & { writes( "< " )
	    ee( 0, uu )
	    ee1 := &null }

	kk := 1 }
    }
case p1 of {
    &null : { close( gg )
	remove( "ile_main" )
	remove( "ile_main.icn" ) 
	remove( "ile_ile" ) }
	
    1 : { remove( "lice_main.c" )
	remove( "lice_main" ) }
    }
end

# Expression recording.
procedure ee( eeq, uu, vv1 )
vv8 := []
vv4 := []
vv7 := "    "
if eeq = 0 then {  
    type( vv1 ) ~== "file" & { 
	integer( vv1 ) & {
	    every vv6 := !uu do if vv6 == vv7 then put( vv8, vv6 ) else { put( vv4, put( vv8, vv6 ) )
		vv8 := [] }

	    vv9 := *vv8
	    if vv9 > 0 then uu := uu[ 1:-( vv9 + 1 ) ] else pull( uu )
	    pull( vv4[ -1 ] )
	    ww( vv4 )
	    return uu[ vv1 + 1:0 ] }
	     
	writes( vv1 )
	vv1 := &null }

    every j := !uu do { writes( vv1, j == vv7 ) | write( vv1, j ) }
    } else every 1 to eeq do put( uu, writes( vv7 ) ) 
end

# Expression reconstruction.
procedure ww( hh, vv2 )
every g := !hh do if type( g ) == "list" then ee( 0, g, vv2 ) else write( vv2, g )    
end

# Editor access
procedure cc2( nn, p )
bb := open( "ile_ile", "crw" )
system( "cp " || \nn || " ile_ile" )
\p & system( "editor" || " ile_ile" )
return bb
end

procedure p3( p31 )
q3 := v + d + n
p31 ? while ll := move( 1 ) do { case ll of {
    "[" : d -:= 1
    "]" : d +:= 1
    "(" : v -:= 1
    ")" : v +:= 1
    "{" : n -:= 1
    "}" : n +:= 1 } }

q2 := q3 - ( d + v + n )
if 0 < q2 then q -:= 1 else ( 0 > q2 & ( q +:= 1 ) )
end
