## read-eval-print-loop-g.pkg
#
# This generates the top-level read-evaluate-print
# loop for interactive compiler sessions.
#
# For higher-level context, see comments at top of
#
#
src/app/makelib/main/makelib-g.pkg#
src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg#
#
#
# Compile-time invocation
# -----------------------
#
# The 'compile' argument gives us an abstract
# interface to the actual mechanics of generating
# executable machine code from a syntax tree.
#
#
#
# Run-time invocation
# -------------------
#
# At start of execution
#
#
src/lib/core/internal/make-mythryld-executable.pkg#
# calls run_commandline in
#
#
src/app/makelib/main/makelib-g.pkg#
# to process commandline arguments, print
# the start-up banner and such, and then
# (for an interactive session) invokes our
#
# read_eval_print_from_user
#
# entrypoint via the trivial 'read_eval_print_from_user' wrapper in
#
#
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg#
#
# See also:
#
src/lib/core/init/read-eval-print-hook.pkg#
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg# Compiled by:
#
src/lib/compiler/core.sublib
### "We make a living by what we get, but
### we make a life by what we give."
###
### -- Winston Churchill
stipulate
package cms = compiler_mapstack_set; # compiler_mapstack_set is from
src/lib/compiler/toplevel/compiler-state/compiler-mapstack-set.pkg package cs = compiler_state; # compiler_state is from
src/lib/compiler/toplevel/interact/compiler-state.pkg package ds = deep_syntax; # deep_syntax is from
src/lib/compiler/front/typer-stuff/deep-syntax/deep-syntax.pkg package ctl = global_controls; # global_controls is from
src/lib/compiler/toplevel/main/global-controls.pkg package cw = callcc_wrapper; # callcc_wrapper is from
src/lib/compiler/execution/main/callcc-wrapper.pkg package cx = compilation_exception; # compilation_exception is from
src/lib/compiler/front/basics/map/compilation-exception.pkg package ed = typer_debugging; # typer_debugging is from
src/lib/compiler/front/typer/main/typer-debugging.pkg package err = error_message; # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkg package fat = fate; # fate is from
src/lib/std/src/nj/fate.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package ims = inlining_mapstack; # inlining_mapstack is from
src/lib/compiler/toplevel/compiler-state/inlining-mapstack.pkg package it = import_tree; # import_tree is from
src/lib/compiler/execution/main/import-tree.pkg package ph = picklehash; # picklehash is from
src/lib/compiler/front/basics/map/picklehash.pkg package lt = linking_mapstack; # linking_mapstack is from
src/lib/compiler/execution/linking-mapstack/linking-mapstack.pkg package seg = code_segment; # code_segment is from
src/lib/compiler/execution/code-segments/code-segment.pkg package acf = anormcode_form; # anormcode_form is from
src/lib/compiler/back/top/anormcode/anormcode-form.pkg package iox = io_exceptions; # io_exceptions is from
src/lib/std/src/io/io-exceptions.pkg package lrp = link_and_run_package; # link_and_run_package is from
src/lib/compiler/execution/main/link-and-run-package.pkg package mcv = mythryl_compiler_version; # mythryl_compiler_version is from
src/lib/core/internal/mythryl-compiler-version.pkg package myp = mythryl_parser; # mythryl_parser is from
src/lib/compiler/front/parser/main/mythryl-parser.pkg package pcs = per_compile_stuff; # per_compile_stuff is from
src/lib/compiler/front/typer-stuff/main/per-compile-stuff.pkg package pm = parse_mythryl; # parse_mythryl is from
src/lib/compiler/front/parser/main/parse-mythryl.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkg package cv = compiler_verbosity; # compiler_verbosity is from
src/lib/compiler/front/basics/main/compiler-verbosity.pkg package prs = prettyprint_raw_syntax; # prettyprint_raw_syntax is from
src/lib/compiler/front/typer/print/prettyprint-raw-syntax.pkg package rpc = runtime_internals::rpc; # runtime_internals is from
src/lib/std/src/nj/runtime-internals.pkg package rsj = raw_syntax_junk; # raw_syntax_junk is from
src/lib/compiler/front/parser/raw-syntax/raw-syntax-junk.pkg package raw = raw_syntax; # raw_syntax is from
src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg package sci = sourcecode_info; # sourcecode_info is from
src/lib/compiler/front/basics/source/sourcecode-info.pkg package syx = symbolmapstack; # symbolmapstack is from
src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack.pkg package tbi = winix_base_text_file_io_driver_for_posix__premicrothread; # winix_base_text_file_io_driver_for_posix__premicrothread is from
src/lib/std/src/io/winix-base-text-file-io-driver-for-posix--premicrothread.pkg package un = unsafe; # unsafe is from
src/lib/std/src/unsafe/unsafe.pkg package urs = unparse_raw_syntax; # unparse_raw_syntax is from
src/lib/compiler/front/typer/print/unparse-raw-syntax.pkg package wnx = winix__premicrothread; # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkg package wpr = write_time_profiling_report; # write_time_profiling_report is from
src/lib/compiler/debugging-and-profiling/profiling/write-time-profiling-report.pkg package xs = exceptions; # exceptions is from
src/lib/std/exceptions.pkg package tmp = highcode_codetemp; # highcode_codetemp is from
src/lib/compiler/back/top/highcode/highcode-codetemp.pkg #
# include package compiler_mapstack_set; # compiler_mapstack_set is from
src/lib/compiler/toplevel/compiler-state/compiler-mapstack-set.pkg# include package pp;
nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkgherein
# This generic is invoked (only) from:
#
#
src/lib/compiler/toplevel/compiler/mythryl-compiler-g.pkg #
generic package read_eval_print_loop_g (
#
cpl: Toplevel_Translate_Raw_Syntax_To_Execode # Toplevel_Translate_Raw_Syntax_To_Execode is from
src/lib/compiler/toplevel/main/translate-raw-syntax-to-execode.api ) # "cpl" == "compile".
: (weak) Read_Eval_Print_Loop # Read_Eval_Print_Loop is from
src/lib/compiler/toplevel/interact/read-eval-print-loop.api {
exception CONTROL_C_SIGNAL; # PUBLIC
# Variable = tmp::Codetemp;
fun say msg
=
{ ctl::print::say msg;
ctl::print::flush ();
};
exception END_OF_FILE;
#
fun interruptible f x # Execute f(x); if POSIX SIGINT signal (^C) is received while f(x) is running, raise CONTROL_C_SIGNAL. In other words, run a possibly long computation with user allowed to ^C out of it.
= # This had obvious application and functionality in single-threaded SML/NJ; it is less clear what it should (or can) do in Mythryl where we have multiple hostthreads and multiple microthreads. -- 2015-09-21 CrT
{ old_fate = *un::sigint_fate;
#
un::sigint_fate # Set up a handler so a SIGINT signal (typically generated by Ctrl-C) coming in will result in the CONTROL_C_SIGNAL exception being raised.
:= # XXX BUGGO FIXME this isn't going to work multithreaded!
fat::call_with_current_fate # The SIGINT handler handle_int() calls *un::sigint_fate -- established in
src/lib/core/internal/make-mythryld-executable.pkg (\\ fate
=
{ fat::call_with_current_fate
(\\ fate' = (fat::switch_to_fate fate fate') ); #
#
raise exception CONTROL_C_SIGNAL;
}
);
( f x # Execute given f(x) computation.
then #
un::sigint_fate := old_fate # Restore original SIGINT handler and return result of f(x).
)
except
e = { un::sigint_fate := old_fate; # f(x) resulted in an exception. Restore the original SIGINT handler...
# #
raise exception e; # ... and re-raise the exception.
};
};
exception EXCEPTION_DURING_EXECUTION Exception;
# ``Here is the core loop handling user interaction
# at the interactive prompt.
#
# ``The base_dictionary and local_dictionary are refs
# so that a top-level command can re-assign either
# one of them and have the next iteration of the loop
# see the new value.
#
# ``It is important that the toplevel environment fate
# NOT see the "fetched" dictionary, but only the REF:
# This way, if the user "filters" the dictionary REF
# a smaller image can be written.''
#
# -- Matthias Blume (?) circa 2000 (?)
stipulate
#
fun read_eval_print_loop
{
sourcecode_info: sci::Sourcecode_Info,
keep_looping: Bool
}
=
{ cv = cv::print_expression_value; # Probably should not be hardwiring this here, but not clear where it should be coming from.
#
prompt_read_parse_and_return_one_toplevel_mythryl_expression
=
pm::prompt_read_parse_and_return_one_toplevel_mythryl_expression
#
sourcecode_info;
# parse_nada::prompt_read_parse_and_return_one_toplevel_nada_expression # Experimental provision for supporting an alternate syntax via an alternate parser.
# sourcecode_info; # If this goes production, we should have a control settable via commandline switch(?)
# with an 'if' here to select which one to use.
per_compile_stuff # per_compile_stuff is from
src/lib/compiler/front/typer-stuff/main/per-compile-stuff.pkg = #
cpl::make_per_compile_stuff # This record actually just contains stuff like a stamp generator and optional prettyprinter,
{ # nothing really core to the compile like sourcecode, parsetree or symbol table -- the serious
sourcecode_info, # symbol table stuff is in compiler_state.
deep_syntax_transform => \\ x = x, # This can be used to profile or instrument code or insert debug support code. This transform gets applied in
src/lib/compiler/front/typer/main/type-package-language-g.pkg
prettyprinter_or_null => NULL,
compiler_verbosity => pcs::print_everything
};
#
fun raise_compile_error_if_compile_errors s
=
if (pcs::saw_errors per_compile_stuff)
#
raise exception err::COMPILE_ERROR;
fi;
fun evaluate_and_print_toplevel_mythryl_declaration raw_declaration
=
{
top_level_pkg_etc_defs_jar = cs::get_top_level_pkg_etc_defs_jar ();
baselevel_pkg_etc_defs_jar = cs::get_baselevel_pkg_etc_defs_jar ();
#
fun get_current_compiler_mapstack_set ()
=
cms::layer_compiler_mapstack_sets
(
top_level_pkg_etc_defs_jar.get_mapstack_set (),
baselevel_pkg_etc_defs_jar.get_mapstack_set ()
);
print_depth = control_print::print_depth;
(get_current_compiler_mapstack_set ())
->
{ symbolmapstack,
linking_mapstack,
inlining_mapstack
};
crossmodule_inlining_aggressiveness
=
ctl::inline::get ();
#
fun debug_print
#
(debugging: Ref( Bool ))
#
( msg: String,
printfn: pp::Prettyprinter -> X -> Void,
arg: X
)
=
if *debugging
#
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
{ pp.box {. pp.rulename "repl1";
pp.lit msg;
pp.newline();
pp.box {. pp.rulename "repl2";
printfn pp arg;
};
};
pp.newline();
}
);
fi;
fun unparse_raw_syntax_tree_debug
( msg,
declaration
)
=
debug_print
ctl::unparse_raw_syntax_tree
( msg,
unparse_raw_syntax_tree_declaration,
declaration
)
where
fun unparse_raw_syntax_tree_declaration
prettyprinter
declaration
=
urs::unparse_declaration
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
end;
#
fun prettyprint_raw_syntax_tree_debug
( msg,
declaration
)
=
{ fun prettyprint_raw_syntax_tree_declaration
prettyprinter
declaration
=
prs::prettyprint_declaration
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
ctl::prettyprint_raw_syntax_tree
( msg,
prettyprint_raw_syntax_tree_declaration,
declaration
);
};
#
fun print_raw_syntax_tree_as_nada_debug (msg, declaration) # More experimental alternate syntax support.
=
{ fun print_raw_syntax_tree_as_nada prettyprinter declaration
=
print_raw_syntax_tree_as_nada::print_declaration_as_nada
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print (ctl::unparse_raw_syntax_tree) (msg, print_raw_syntax_tree_as_nada, declaration);
};
#
fun unparse_deep_syntax_tree_debug (msg, declaration)
=
{ fun unparse_deep_syntax_tree_declaration prettyprinter declaration
=
unparse_deep_syntax::unparse_declaration # unparse_deep_syntax is from
src/lib/compiler/front/typer/print/unparse-deep-syntax.pkg (symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
(ctl::unparse_deep_syntax_tree)
( msg,
unparse_deep_syntax_tree_declaration,
declaration
);
};
#
fun print_deep_syntax_tree_as_nada_debug (msg, declaration) # More experimental alternate syntax support.
=
{ fun print_deep_syntax_tree_as_nada prettyprinter declaration
=
print_deep_syntax_as_nada::print_declaration_as_nada
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
(ctl::unparse_deep_syntax_tree)
( msg,
print_deep_syntax_tree_as_nada,
declaration
);
};
# NB: The difference between unparsing and prettyprinting is that unparsing tries to reproduce the original sourcecode but prettyprinting just dumps the parsetree datastructure literally.
unparse_raw_syntax_tree_debug( "Raw_Syntax: ", raw_declaration); # Testing code to print raw_declaration.
prettyprint_raw_syntax_tree_debug( "Raw_Syntax: ", raw_declaration); # Testing code to print raw_declaration.
# print_raw_syntax_tree_as_nada_debug( "LIB7_SYNTAX:", raw_declaration); # Testing code to translate raw_declaration to lib7.
# "Returning deep_syntax_tree and
# exported_highcode_variables here
# is a bad idea: They hold on to
# things unnecessarily.- # (But they are used in the prettyprint_declaration below. --CrT)
# This must be fixed in the long run."
# -- Zhong # XXX SUCKO FIXME
#
# We do this one other place:
#
src/app/makelib/compile/compile-in-dependency-order-g.pkg #
(cpl::translate_raw_syntax_to_execode
{
sourcecode_info,
raw_declaration,
#
symbolmapstack,
inlining_mapstack,
#
per_compile_stuff,
handle_compile_errors => raise_compile_error_if_compile_errors,
crossmodule_inlining_aggressiveness,
#
compiledfile_version => () # We don't have real on-disk compiled-code binaries here, we're just compiling console strings to memory.
})
->
{ code_and_data_segments,
new_symbolmapstack,
deep_syntax_declaration,
export_picklehash,
exported_highcode_variables,
import_trees,
inline_expression,
...
};
package_closure
=
lrp::make_package_closure
{
code_and_data_segments,
exception_wrapper => EXCEPTION_DURING_EXECUTION
}
then raise_compile_error_if_compile_errors ();
package_closure
=
cw::trap_callcc (interruptible package_closure);
rpc::this_fn_profiling_hook_refcell__global # Ultimately from src/c/main/construct-runtime-package.c
:=
wpr::in_other_code__cpu_user_index;
new_linking_mapstack
=
if *ctl::execute_compiled_code # TRUE unless manually overriden.
#
lrp::link_and_run_package_closure
{
package_closure, # Package being linked into memory image.
import_trees, # Values which it needs to import from other packages.
linking_mapstack, # Values available for import from other packages.
export_picklehash # 'Name' under which exports from this package will be published.
};
else
linking_mapstack; # This is a delta including only exports from this package.
fi;
rpc::this_fn_profiling_hook_refcell__global # Ultimately from src/c/main/construct-runtime-package.c
:=
wpr::in_compiler__cpu_user_index; # Remember that we are now "in compiler" for CPU-cycle-accounting purposes.
new_compiler_mapstack_set
=
cms::make_compiler_mapstack_set
{
symbolmapstack => new_symbolmapstack,
linking_mapstack => new_linking_mapstack,
#
inlining_mapstack => ims::make_inlining_mapstack
( export_picklehash,
inline_expression
)
};
# Re-fetch toplevel tables because execution
# may have changed their contents:
#
new_local_compiler_mapstack_set
=
cms::concatenate_compiler_mapstack_sets
(
new_compiler_mapstack_set,
top_level_pkg_etc_defs_jar.get_mapstack_set ()
);
# Install any new package defs etc
# in the global environment:
#
top_level_pkg_etc_defs_jar.set_mapstack_set
#
new_local_compiler_mapstack_set;
#
# NB: We install the new local compiler state
# before printing: Otherwise we would
# find ourselves in trouble if the
# autoloader changed the the contents
# of loc out from under our feet:
#
fun look_and_load symbol
=
{ fun get ()
=
syx::get
( cms::symbolmapstack_part (get_current_compiler_mapstack_set ()),
symbol
);
get ()
except
syx::UNBOUND = get ();
};
# Notice that even through several potential rounds
# the result of get_symbols is constant (up to list
# order), so memoization (as performed by
# syx::special) is ok.
#
fun get_symbols ()
=
{ symbolmapstack
=
cms::symbolmapstack_part
(get_current_compiler_mapstack_set ());
syx::symbols symbolmapstack;
};
symbolmapstack1
=
syx::special
(
look_and_load,
get_symbols
);
e0 = get_current_compiler_mapstack_set ();
e1 = cms::make_compiler_mapstack_set
{
symbolmapstack => symbolmapstack1,
linking_mapstack => cms::linking_part e0,
inlining_mapstack => cms::inlining_part e0
};
unparse_deep_syntax_tree_debug( "Deep_Syntax:", deep_syntax_declaration); # Testing code to print deep_syntax_tree.
# print_deep_syntax_tree_as_nada_debug( "LIB7_SYNTAx:", deep_syntax_declaration); # Testing code to translate deep_syntax_tree to lib7.
if *myp::print_interactive_prompts
#
print "\n";
fi;
if *myp::unparse_result
#
# Print the result of the evaluated expression:
#
pp::with_standard_prettyprinter
#
sourcecode_info.error_consumer [] # unparse_interactive_deep_syntax_declaration is from
src/lib/compiler/src/print/unparse-interactive-deep-syntax-declaration.pkg #
(\\ pp: pp::Prettyprinter
=
unparse_interactive_deep_syntax_declaration::unparse_declaration
e1
(pp, cv)
(deep_syntax_declaration, exported_highcode_variables)
);
fi;
}; # fun evaluate_and_print_toplevel_mythryl_declaration
fun evaluate_and_print_toplevel_mythryl_declarations []
=>
();
evaluate_and_print_toplevel_mythryl_declarations (declaration ! declarations)
=>
{ evaluate_and_print_toplevel_mythryl_declaration declaration;
evaluate_and_print_toplevel_mythryl_declarations declarations;
};
end;
#
fun prompt_read_evaluate_and_print_one_toplevel_mythryl_expression ()
=
case (prompt_read_parse_and_return_one_toplevel_mythryl_expression ())
#
THE raw_declaration => evaluate_and_print_toplevel_mythryl_declarations (rsj::extract_toplevel_declarations raw_declaration);
NULL => raise exception END_OF_FILE;
esac;
#
# The point of the
#
# rsj::extract_toplevel_declarations
#
# call above is that the current
#
# src/lib/compiler/front/parser/yacc/mythryl.grammar
#
# returns the entire body of a Mythryl script as a single
# raw-syntax tree, but we need scripts like
#
# #!/usr/bin/mythryl
# use "foo.lib";
# foo::whatever();
#
# to compile and execute one statement at a time,
# otherwise package 'foo' will come up undefined
# during compilation of 'foo::whatever();', because
# that becomes defined only after 'load "foo.lib";'
# has actually executed.
#
# To fix this problem we use rsj::extract_toplevel_declarations
# to break the script syntax tree back into its natural parts,
# and then call evaluate_and_print_toplevel_mythryl_declaration
# separately on each part. -- 2012-01-22 CrT
#
fun inner_read_eval_print_loop ()
=
{ prompt_read_evaluate_and_print_one_toplevel_mythryl_expression ();
inner_read_eval_print_loop ();
};
#
# This is the core interactive
# read-eval-print loop.
#
# You might expect to find the
# the interactive prompt printed out
# here, but in fact the code for
# -that- is buried deep in the
# get_line ()
# function in
#
src/lib/compiler/front/parser/main/mythryl-parser-guts.pkg #
# The actual prompt strings are kept in
# myp::primary_prompt and
# myp::secondary_prompt
interruptible
if keep_looping inner_read_eval_print_loop;
else prompt_read_evaluate_and_print_one_toplevel_mythryl_expression;
fi
();
}; # fun read_eval_print_loop
herein
#
fun with_exception_trapping # PUBLIC.
#
{ treat_as_user: Bool,
pp: Null_Or( pp::Prettyprinter )
}
#
{ thunk: Void -> Void,
flush: Void -> Void,
fate: Exception -> Void
}
=
{
say = case pp
#
THE pp => say
where
fun say (msg: String)
=
{ pp.lit msg;
pp.newline();
};
end;
NULL => say;
esac;
# fun show_history' [s] => say (cat [" raised at: ", s, "\n"]);
# show_history' (s ! r) => { show_history' r; say (cat [" ", s, "\n"]);};
# show_history' [] => ();
# end;
fun show_history' [s] => {
say (cat [" raised at: ", s, "\n"]);
};
show_history' (s ! r) => {
show_history' r;
say (cat [" ", s, "\n"]);
};
show_history' [] => ();
end;
#
fun exception_message
(cx::COMPILE s)
=>
cat ["Compile: \"", s, "\""];
exception_message exception'
=>
xs::exception_message
exception';
end;
#
fun show_history exception'
=
show_history'
(lib7::exception_history exception');
#
fun user_handle (EXCEPTION_DURING_EXECUTION exception')
=>
user_handle exception';
user_handle exception'
=>
{
msg = exception_message exception';
name = exception_name exception';
if (name == "CONTROL_C_SIGNAL")
# 2008-01-07 CrT: This case wasn't here originally,
# and is probably only needed due to
# my screwing up the logic elsewhere.
#
# (Before my last round of frigging around,
# the non-bt_handle CONTROL_C_SIGNAL case
# was handling this.) XXX BUGGO FIXME
#
say "\nCaught <CTRL>-C. (Do <CTRL>-D to exit.)";
else
if (msg == name) say (cat ["\nUncaught exception ", name, "\n"]);
else say (cat ["\nUncaught exception ", name, " [", msg, "]\n"]);
fi;
show_history exception';
fi;
flush ();
fate exception';
};
end;
#
fun bug_handle exception'
=
{
msg = exception_message exception';
name = exception_name exception';
say (cat ["\nUnexpected exception (bug?): ", name, " [", msg, "]\n"]);
show_history exception';
flush();
fate exception';
};
#
fun non_bt_handle exception' # "bt" might be "base type" here... ?
=
case exception'
#
END_OF_FILE
=>
say "\n";
(CONTROL_C_SIGNAL
| EXCEPTION_DURING_EXECUTION CONTROL_C_SIGNAL)
=>
{
say "\nSignal caught. (Do <CTRL>-D to exit.)\n";
flush();
fate exception';
};
err::COMPILE_ERROR
=>
{
flush();
fate exception';
};
cx::COMPILE "syntax error"
=>
{
flush();
fate exception';
};
cx::COMPILE s
=>
{
say (cat ["\nUncaught exception COMPILE: \"", s, "\"\n"]);
flush();
fate exception';
};
cw::TOPLEVEL_CALLCC
=>
{
say("Error: throw from one top-level expression into another\n");
flush ();
fate exception';
};
(lrp::LINK
| EXCEPTION_DURING_EXECUTION lrp::LINK)
=>
{
flush ();
fate exception';
};
EXCEPTION_DURING_EXECUTION exception''
=>
{
user_handle exception'';
};
exception''
=>
{
if treat_as_user user_handle exception'';
else bug_handle exception'';
fi;
};
esac;
runtime_internals::tdp::with_monitors # runtime_internals is from
src/lib/std/src/nj/runtime-internals.pkg FALSE
thunk
except
e = non_bt_handle e;
}; # fun with_exception_trapping
# Interactive loop, with error handling.
#
# We wind up here primarily to execute
# #!/usr/bin/mythryl
# scripts:
#
# o Logic in
# src/c/o/mythryl.c
# invokes /usr/bin/mythryld
# with the unix environment setting
# MYTHRYL_SCRIPT=<stdin>
#
# o Our main executable
# /usr/bin/mythryld
# starts execution near the bottom of
#
src/lib/core/internal/mythryld-app.pkg # where the first thing it does is check
# MYTHRYL_SCRIPT and if it is set (to script_name) it
#
# * Sets
# mythryl_parser::print_interactive_prompts := FALSE;
# to suppress interactive prompting;
#
# * Skips commandline switch processing,
# and thus the usual
#
src/app/makelib/main/makelib-g.pkg # entry into read_eval_print_from_user()
# in this file.
#
# * Invokes read_eval_print_from_script() in
#
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg # which promptly invokes us.
#
fun read_eval_print_from_script file_name # PUBLIC. 'file_name' can be "<stdin>" else filename for script -- in practice, currently always the former.
=
{
source_stream
=
if (file_name == "<stdin>") fil::stdin;
else fil::open_for_read file_name;
fi;
source = sci::make_sourcecode_info
{
file_name,
line_num => 1,
source_stream,
is_interactive => TRUE, # ?
error_consumer => err::default_plaint_sink ()
};
#
fun flush' ()
=
();
# case (fil::max_readable_without_blocking # Commented out 2012-12-23 CrT because this is basically the only use and the whole idea of max_readable_without_blocking() seems ill-advised -- encourages polling.
# (
# fil::stdin,
# 4096
# ))
#
# (NULL
| THE 0)
# =>
# ();
#
# THE _
# =>
# { ignore (fil::read fil::stdin);
# flush'();
# };
# esac;
#
fun flush ()
=
{ source.saw_errors := FALSE;
#
flush' ()
except
iox::IO _ = ();
};
#
# We want scripts to exit cleanly on the first
# uncaught exception, so we do NOT loop here
# after catching one:
with_exception_trapping
{ treat_as_user => FALSE,
pp => NULL
}
{ thunk => \\ () = read_eval_print_loop { sourcecode_info => source, keep_looping => TRUE },
flush,
fate => ignore
};
}; # fun read_eval_print_from_script
fun input_is_tty f # This fn is duplicated between here and
src/app/makelib/main/makelib-g.pkg XXX SUCKO FIXME (Should probably be a standard library function anyhow.)
=
{ (fil::pur::get_reader (fil::get_instream f))
->
(rd, buf);
is_tty = case rd
#
tbi::FILEREADER { io_descriptor => THE iod, ... }
=>
(wnx::io::iod_to_iodkind iod == wnx::io::CHAR_DEVICE);
_ => FALSE;
esac;
# Since getting the reader will have terminated
# the stream, we now need to build a new stream:
#
fil::set_instream
(f, fil::pur::make_instream (rd, buf) );
is_tty;
};
fun read_eval_print_from_stream # PUBLIC.
(
(file_name: String), # Filename for 'stream', else "<Input_Stream>" or such.
(source_stream: fil::Input_Stream)
)
= # We get wrapped in
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg { # mythryl_compiler_compiler_g that wrapper to compile_in_dependency_order_g
# where it gets used in maybe_compile_and_run_mythryl_codestring to compile the
# facility to compile and run little code fragments before/after each file compile.
#
# mythryl_compiler_compiler_g is from
src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg # compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg is_interactive = input_is_tty source_stream;
#
source = sci::make_sourcecode_info
{
file_name, # Filename for 'stream', else "<Input_Stream>" or such.
line_num => 1,
source_stream,
is_interactive,
error_consumer => err::default_plaint_sink ()
};
read_eval_print_loop { sourcecode_info => source, keep_looping => TRUE }
except
exception'
=
{ sci::close_source source;
#
case exception'
#
END_OF_FILE => ();
_ => raise exception exception';
esac;
};
};
#
fun parse_string_to_raw_declarations # PUBLIC. This facility created for
src/lib/x-kit/widget/edit/eval-mode.pkg { #
sourcecode_info: sci::Sourcecode_Info, # Source code to compile, also error sink.
pp: pp::Prettyprinter # Where to prettyprint results.
} #
: #
List( raw::Declaration ) #
=
{
prompt_read_parse_and_return_one_toplevel_mythryl_expression
=
pm::prompt_read_parse_and_return_one_toplevel_mythryl_expression
#
sourcecode_info;
result = REF ([]: List(raw::Declaration));
fun parse_one_toplevel_mythryl_expression ()
=
case (prompt_read_parse_and_return_one_toplevel_mythryl_expression ())
#
THE raw_declaration
=>
result := rsj::extract_toplevel_declarations raw_declaration;
NULL => ();
esac;
fun do_it_with_exception_trapping () # I do not know if the parser throws exceptions, but I presume it does in the case of syntax errors.
= # If not, we can dispense with this stuff. -- 2015-09-27 CrT
{
with_exception_trapping
{ treat_as_user => FALSE,
pp => THE pp
}
{ thunk => parse_one_toplevel_mythryl_expression,
flush => \\ () = (),
fate => ignore
};
};
interruptible # Trap CTRL-C (i.e. Posix SIGINT interrupts). I've retained this from parent code mostly as a guide to future interrupt trapping if desired,
do_it_with_exception_trapping # but while in single-threaded SML/NJ this was obviously desirable and the required functionality clear, in the multi-hostthreaded, multi-microthreaded
(); # Mythryl context is is far from clear that this is useful, or what its functionality should be. (Also mythryl-emacs traps ^C anyhow!) -- 2015-09-21 CrT
*result;
}; # fun parse_string_to_raw_declarations
# # so I thought it was better to clone-and-mutate than to add more conditionals and make it an even bigger mess. -- 2015-09-09 CrT
fun compile_raw_declaration_to_package_closure # PUBLIC. This facility created for
src/lib/x-kit/widget/edit/eval-mode.pkg { #
declaration: raw::Declaration, #
sourcecode_info: sci::Sourcecode_Info, # Source code to compile, also error sink.
pp: pp::Prettyprinter, # Where to prettyprint results.
compiler_state_stack: (cs::Compiler_State, List(cs::Compiler_State)), # Compiler symbol tables to use for this compile.
options: List( cs::Compile_And_Eval_String_Option ) # Future-proofing, lets us add more parameters in future without breaking backward compatibility at the client-call level.
} #
: #
Null_Or (
{ package_closure: seg::Package_Closure,
import_trees: List( it::Import_Tree ),
export_picklehash: Null_Or( ph::Picklehash ),
linking_mapstack: lt::Picklehash_To_Heapchunk_Mapstack,
code_and_data_segments: seg::Code_And_Data_Segments,
new_symbolmapstack: syx::Symbolmapstack, # A symbol table delta containing (only) stuff from raw_declaration.
deep_syntax_declaration: ds::Declaration, # Typechecked form of raw_declaration.
exported_highcode_variables: List( tmp::Codetemp ),
inline_expression: Null_Or( acf::Function ),
top_level_pkg_etc_defs_jar: cs::Compiler_Mapstack_Set_Jar,
get_current_compiler_mapstack_set: Void -> cs::Compiler_Mapstack_Set,
compiler_verbosity: pcs::Compiler_Verbosity,
compiler_state_stack: (cs::Compiler_State, List(cs::Compiler_State))
}
)
=
{
Compile_And_Eval_String_Options
=
{ compiler_verbosity: pcs::Compiler_Verbosity,
deep_syntax_transform: ds::Declaration -> ds::Declaration
};
fun process_options (options: List( cs::Compile_And_Eval_String_Option ))
=
{ my_compiler_verbosity = REF pcs::print_expression_value;
my_deep_syntax_transform = REF (\\ x = x);
#
apply do_option options
where
fun do_option (cs::COMPILER_VERBOSITY v) => my_compiler_verbosity := v;
do_option (cs::DEEP_SYNTAX_TRANSFORM t) => my_deep_syntax_transform := t;
end;
end;
{ compiler_verbosity => *my_compiler_verbosity,
deep_syntax_transform => *my_deep_syntax_transform
};
};
(process_options options)
->
{ compiler_verbosity,
deep_syntax_transform
};
per_compile_stuff # per_compile_stuff is from
src/lib/compiler/front/typer-stuff/main/per-compile-stuff.pkg = #
cpl::make_per_compile_stuff # This record actually just contains stuff like a stamp generator and optional prettyprinter,
{ # nothing really core to the compile like sourcecode, parsetree or symbol table -- the serious
sourcecode_info, # symbol table stuff is in compiler_state.
deep_syntax_transform, # This can be used to profile or instrument code or insert debug support code. This transform gets applied in
src/lib/compiler/front/typer/main/type-package-language-g.pkg prettyprinter_or_null => THE pp,
compiler_verbosity
};
fun raise_compile_error_if_compile_errors s
=
if (pcs::saw_errors per_compile_stuff)
#
raise exception err::COMPILE_ERROR;
fi;
fun compile_toplevel_mythryl_declaration
(
raw_declaration: raw::Declaration,
compiler_state_stack: (cs::Compiler_State, List(cs::Compiler_State))
)
=
{
compiler_state_stack
->
( compiler_state: cs::Compiler_State,
compiler_states: List( cs::Compiler_State )
);
top_level_pkg_etc_defs_jar = compiler_state.top_level_pkg_etc_defs_jar;
baselevel_pkg_etc_defs_jar = compiler_state.baselevel_pkg_etc_defs_jar;
#
fun get_current_compiler_mapstack_set ()
=
cms::layer_compiler_mapstack_sets
(
top_level_pkg_etc_defs_jar.get_mapstack_set (),
baselevel_pkg_etc_defs_jar.get_mapstack_set ()
);
print_depth = control_print::print_depth;
(get_current_compiler_mapstack_set ())
->
{ symbolmapstack,
linking_mapstack,
inlining_mapstack
};
crossmodule_inlining_aggressiveness
=
ctl::inline::get ();
#
fun debug_print
#
(debugging: Ref( Bool ))
#
( msg: String,
printfn: pp::Prettyprinter -> X -> Void,
arg: X
)
=
if *debugging
#
pp.box {. pp.rulename "repl1";
pp.lit msg;
pp.newline();
pp.box {. pp.rulename "repl2";
printfn pp arg;
};
};
pp.newline();
fi;
fun unparse_raw_syntax_tree_debug
( msg,
declaration
)
=
debug_print
ctl::unparse_raw_syntax_tree
( msg,
unparse_raw_syntax_tree_declaration,
declaration
)
where
fun unparse_raw_syntax_tree_declaration
prettyprinter
declaration
=
urs::unparse_declaration
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
end;
#
fun prettyprint_raw_syntax_tree_debug
( msg,
declaration
)
=
{ fun prettyprint_raw_syntax_tree_declaration
prettyprinter
declaration
=
prs::prettyprint_declaration
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
ctl::prettyprint_raw_syntax_tree
( msg,
prettyprint_raw_syntax_tree_declaration,
declaration
);
};
#
fun print_raw_syntax_tree_as_nada_debug (msg, declaration) # More experimental alternate syntax support.
=
{ fun print_raw_syntax_tree_as_nada prettyprinter declaration
=
print_raw_syntax_tree_as_nada::print_declaration_as_nada
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print (ctl::unparse_raw_syntax_tree) (msg, print_raw_syntax_tree_as_nada, declaration);
};
#
fun unparse_deep_syntax_tree_debug (msg, declaration)
=
{ fun unparse_deep_syntax_tree_declaration prettyprinter declaration
=
unparse_deep_syntax::unparse_declaration # unparse_deep_syntax is from
src/lib/compiler/front/typer/print/unparse-deep-syntax.pkg (symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
(ctl::unparse_deep_syntax_tree)
( msg,
unparse_deep_syntax_tree_declaration,
declaration
);
};
#
fun print_deep_syntax_tree_as_nada_debug (msg, declaration) # More experimental alternate syntax support.
=
{ fun print_deep_syntax_tree_as_nada prettyprinter declaration
=
print_deep_syntax_as_nada::print_declaration_as_nada
(symbolmapstack, NULL)
prettyprinter
(declaration, *print_depth);
debug_print
(ctl::unparse_deep_syntax_tree)
( msg,
print_deep_syntax_tree_as_nada,
declaration
);
};
# NB: The difference between unparsing and prettyprinting is that unparsing tries to reproduce the original sourcecode but prettyprinting just dumps the parsetree datastructure literally.
unparse_raw_syntax_tree_debug( "Raw_Syntax: ", raw_declaration); # Testing code to print raw_declaration.
prettyprint_raw_syntax_tree_debug( "Raw_Syntax: ", raw_declaration); # Testing code to print raw_declaration.
# print_raw_syntax_tree_as_nada_debug( "LIB7_SYNTAX:", raw_declaration); # Testing code to translate raw_declaration to lib7.
# "Returning deep_syntax_tree and
# exported_highcode_variables here
# is a bad idea: They hold on to
# things unnecessarily.- # (But they are used in the prettyprint_declaration below. --CrT)
# This must be fixed in the long run."
# -- Zhong # XXX SUCKO FIXME
#
# We do this one other place:
#
src/app/makelib/compile/compile-in-dependency-order-g.pkg #
(cpl::translate_raw_syntax_to_execode
{
sourcecode_info,
raw_declaration,
#
symbolmapstack,
inlining_mapstack,
#
per_compile_stuff,
handle_compile_errors => raise_compile_error_if_compile_errors,
crossmodule_inlining_aggressiveness,
#
compiledfile_version => () # We don't have real on-disk compiled-code binaries here, we're just compiling console strings to memory.
})
->
{ code_and_data_segments,
/* */ new_symbolmapstack,
deep_syntax_declaration,
/* */ export_picklehash,
/* */ exported_highcode_variables,
/* */ import_trees,
/* */ inline_expression,
...
};
package_closure
=
lrp::make_package_closure
{
code_and_data_segments,
exception_wrapper => EXCEPTION_DURING_EXECUTION
}
then raise_compile_error_if_compile_errors ();
package_closure
=
cw::trap_callcc (interruptible package_closure);
rpc::this_fn_profiling_hook_refcell__global # Ultimately from src/c/main/construct-runtime-package.c
:=
wpr::in_other_code__cpu_user_index;
THE
{
package_closure, # Package being linked into memory image.
import_trees, # Values which it needs to import from other packages.
linking_mapstack, # Values available for import from other packages.
export_picklehash, # 'Name' under which exports from this package will be published.
code_and_data_segments,
new_symbolmapstack,
deep_syntax_declaration,
exported_highcode_variables,
inline_expression,
top_level_pkg_etc_defs_jar,
get_current_compiler_mapstack_set,
compiler_verbosity,
compiler_state_stack => (compiler_state, compiler_states)
};
}; # fun compile_toplevel_mythryl_declaration
result = REF NULL;
fun do_it ()
=
result := compile_toplevel_mythryl_declaration
( declaration,
compiler_state_stack
);
fun do_it_with_exception_trapping () # The compiler handles errors by throwing an exception, so we need to trap it and return normally.
=
{
with_exception_trapping
{ treat_as_user => FALSE,
pp => THE pp
}
{ thunk => do_it,
flush => \\ () = (),
fate => ignore
};
};
interruptible # Trap CTRL-C (i.e. Posix SIGINT interrupts). I've retained this from parent code mostly as a guide to future interrupt trapping if desired,
do_it_with_exception_trapping # but while in single-threaded SML/NJ this was obviously desirable and the required functionality clear, in the multi-hostthreaded, multi-microthreaded
(); # Mythryl context is is far from clear that this is useful, or what its functionality should be. (Also mythryl-emacs traps ^C anyhow!) -- 2015-09-21 CrT
*result;
}; # fun compile_raw_declaration_to_package_closure
#
fun link_and_run_package_closure # PUBLIC. This facility created for
src/lib/x-kit/widget/edit/eval-mode.pkg { #
sourcecode_info: sci::Sourcecode_Info, # Source code to compile, also error sink.
pp: pp::Prettyprinter # Where to prettyprint results.
}
{ package_closure: seg::Package_Closure,
import_trees: List( it::Import_Tree ),
export_picklehash: Null_Or( ph::Picklehash ),
linking_mapstack: lt::Picklehash_To_Heapchunk_Mapstack,
code_and_data_segments: seg::Code_And_Data_Segments,
new_symbolmapstack: syx::Symbolmapstack, # A symbol table delta containing (only) stuff from raw_declaration.
deep_syntax_declaration: ds::Declaration, # Typechecked form of raw_declaration.
exported_highcode_variables: List( tmp::Codetemp ),
inline_expression: Null_Or( acf::Function ),
top_level_pkg_etc_defs_jar: cs::Compiler_Mapstack_Set_Jar,
get_current_compiler_mapstack_set: Void -> cs::Compiler_Mapstack_Set,
compiler_verbosity: pcs::Compiler_Verbosity,
compiler_state_stack: (cs::Compiler_State, List(cs::Compiler_State)) # Compiler symbol tables to use for this compile.
} #
: #
(cs::Compiler_State, List(cs::Compiler_State)) # Updated compiler symbol tables. Caller may keep or discard.
=
{ compiler_state_stack -> (compiler_state, compiler_states);
#
fun link_and_run
(
)
=
{
#
fun debug_print
#
(debugging: Ref( Bool ))
#
( msg: String,
printfn: pp::Prettyprinter -> X -> Void,
arg: X
)
=
if *debugging
#
pp.box {. pp.rulename "repl1";
pp.lit msg;
pp.newline();
pp.box {. pp.rulename "repl2";
printfn pp arg;
};
};
pp.newline();
fi;
# NB: The difference between unparsing and prettyprinting is that unparsing tries to reproduce the original sourcecode but prettyprinting just dumps the parsetree datastructure literally.
new_linking_mapstack
=
lrp::link_and_run_package_closure
{
package_closure, # Package being linked into memory image.
import_trees, # Values which it needs to import from other packages.
linking_mapstack, # Values available for import from other packages.
export_picklehash # 'Name' under which exports from this package will be published.
};
rpc::this_fn_profiling_hook_refcell__global # Ultimately from src/c/main/construct-runtime-package.c
:=
wpr::in_compiler__cpu_user_index; # Remember that we are now "in compiler" for CPU-cycle-accounting purposes.
new_compiler_mapstack_set
=
cms::make_compiler_mapstack_set
{
symbolmapstack => new_symbolmapstack,
linking_mapstack => new_linking_mapstack,
#
inlining_mapstack => ims::make_inlining_mapstack
( export_picklehash,
inline_expression
)
};
# Re-fetch toplevel tables because execution
# may have changed their contents:
#
new_local_compiler_mapstack_set
=
cms::concatenate_compiler_mapstack_sets
(
new_compiler_mapstack_set,
top_level_pkg_etc_defs_jar.get_mapstack_set ()
);
# Install any new package defs etc
# in our compile environment:
#
top_level_pkg_etc_defs_jar.set_mapstack_set
#
new_local_compiler_mapstack_set;
#
# NB: We install the new local compiler state
# before printing: Otherwise we would
# find ourselves in trouble if the
# autoloader changed the the contents
# of loc out from under our feet.
#
fun look_and_load symbol
=
{ fun get ()
=
syx::get
( cms::symbolmapstack_part (get_current_compiler_mapstack_set ()),
symbol
);
get ()
except
syx::UNBOUND = get ();
};
# Notice that even through several potential rounds
# the result of get_symbols is constant (up to list
# order), so memoization (as performed by
# syx::special) is ok.
#
fun get_symbols ()
=
{ symbolmapstack
=
cms::symbolmapstack_part
(get_current_compiler_mapstack_set ());
syx::symbols symbolmapstack;
};
symbolmapstack1
=
syx::special
(
look_and_load,
get_symbols
);
e0 = get_current_compiler_mapstack_set ();
e1 = cms::make_compiler_mapstack_set
{
symbolmapstack => symbolmapstack1,
linking_mapstack => cms::linking_part e0,
inlining_mapstack => cms::inlining_part e0
};
# unparse_deep_syntax_tree_debug( "Deep_Syntax:", deep_syntax_declaration); # Testing code to print deep_syntax_tree.
# print_deep_syntax_tree_as_nada_debug( "LIB7_SYNTAx:", deep_syntax_declaration); # Testing code to translate deep_syntax_tree to lib7.
# Print the result of the evaluated expression:
#
if compiler_verbosity.print_expression_value
#
unparse_interactive_deep_syntax_declaration::unparse_declaration
e1
(pp, compiler_verbosity)
(deep_syntax_declaration, exported_highcode_variables);
fi;
(compiler_state, compiler_states): (cs::Compiler_State, List(cs::Compiler_State));
}; # fun link_and_run
result = REF compiler_state_stack;
fun link_and_run_package_closure' ()
=
result := link_and_run ();
fun do_it_with_exception_trapping ()
=
{
with_exception_trapping
{ treat_as_user => FALSE,
pp => THE pp
}
{ thunk => link_and_run_package_closure',
flush => \\ () = (),
fate => ignore
};
};
interruptible # Trap CTRL-C (i.e. Posix SIGINT interrupts). I've retained this from parent code mostly as a guide to future interrupt trapping if desired,
do_it_with_exception_trapping # but while in single-threaded SML/NJ this was obviously desirable and the required functionality clear, in the multi-hostthreaded, multi-microthreaded
(); # Mythryl context is is far from clear that this is useful, or what its functionality should be. (Also mythryl-emacs traps ^C anyhow!) -- 2015-09-21 CrT
*result;
}; # fun link_and_run_package_closure
fun read_eval_print_from_user () # PUBLIC. This is the interactive loop used at the Linux commandline, invoked by
src/app/makelib/main/makelib-g.pkg =
{
# is_interactive
# =
# input_is_tty fil::stdin;
print "\n";
print mcv::mythryl_interactive_banner; # Something like: "Mythryl 110.58.3.0.2 built Thu Dec 23 14:11:49 2010"
print "\n(You might prefer to use M-x eval in mythryl-emacs.)";
print "\nDo help(); for help.";
outer_loop ();
}
where
#
fun read_eval_print_from_stream' stream
=
{ source = sci::make_sourcecode_info
{
file_name => "stdin", # "filename"
line_num => 1,
source_stream => stream,
is_interactive => FALSE, # Not interactive.
error_consumer => err::default_plaint_sink ()
};
read_eval_print_loop { sourcecode_info => source, keep_looping => FALSE }
except
exception'
=
{ sci::close_source source;
#
case exception'
#
END_OF_FILE => ();
_ => raise exception exception';
esac;
};
};
#
fun eval_string code_string
=
safely::do
{
open_it => {. fil::open_string code_string; },
close_it => fil::close_input,
cleanup => \\ _ = ()
}
read_eval_print_from_stream';
# Drop any terminal newline:
#
fun chomp line
=
string::is_suffix "\n" line ?? string::substring (line, 0, string::length_in_bytes line - 1)
:: line;
#
# There's another implementation of this fn in
src/lib/std/src/string-guts.pkg # Probably one of them should be dropped. XXX SUCKO FIXME
#
fun main_loop ()
=
{ print *myp::primary_prompt;
#
input_line = fil::read_line fil::stdin;
case input_line
#
THE line
=>
{ eval_string (chomp line + " ;;");
main_loop ();
};
NULL
=>
# EOF on stdin means it
# is time to shut down:
#
wnx::process::exit
wnx::process::success;
esac;
};
#
fun flush' ()
=
();
# case (fil::max_readable_without_blocking # Commented out 2012-12-23 CrT because this is basically the only use and the whole idea of max_readable_without_blocking() seems ill-advised -- encourages polling.
# (
# fil::stdin,
# 4096
# ))
#
# (NULL
| THE 0)
# =>
# ();
#
# THE _ => { ignore (fil::read fil::stdin);
# flush'();
# };
# esac;
#
fun flush ()
=
{
# source.saw_errors := FALSE;
flush' ()
except
iox::IO _ = ();
};
#
fun main_loop_wrapper ()
=
{ include package trap_control_c; # trap_control_c is from
src/lib/std/trap-control-c.pkg #
catch_interrupt_signal
main_loop;
();
};
#
fun outer_loop ()
=
{ with_exception_trapping
#
{ treat_as_user => TRUE,
pp => NULL
}
#
{ thunk => \\ () = { main_loop_wrapper (); (); },
flush => \\ () = { flush (); (); },
fate => \\ _ = { outer_loop (); (); }
};
};
# { thunk => main_loop,
# flush => \\ () = (),
# fate => outer_loop o ignore
# };
# fun loop ()
# =
# { fil::write (fil::stdout, *myp::primary_prompt);
# fil::flush fil::stdout;
# input_line = REF (THE "");
# with_exception_trapping
# { treat_as_user => TRUE,
# pp => NULL
# }
# { thunk => \\ () = input_line := fil::read_line fil::stdin,
# flush => \\ () = (),
# fate => loop o ignore
# };
# input_line
# =
# fil::read_line
# fil::stdin;
# case *input_line
# in
# THE line
# =>
# {
# with_exception_trapping
# { treat_as_user => TRUE,
# pp => NULL
# }
# { thunk => \\ () = eval_string (case (fil::read_line fil::stdin) THE line => line; NULL => ""; esac + " ;;"),
# flush => \\ () = (),
# fate => loop o ignore
# };
#
## eval_string (line + " ;;");
# loop ();
# };
# NULL => ();
# esac;
# };
end;
end;
}; # read_eval_print_loop_g
end; # stipulate