X-Git-Url: http://nitlanguage.org diff --git a/contrib/nitin/nitin.nit b/contrib/nitin/nitin.nit index 149e616..6651636 100644 --- a/contrib/nitin/nitin.nit +++ b/contrib/nitin/nitin.nit @@ -19,9 +19,12 @@ # The Nit interactive interpreter module nitin +import prompt + import nitc::interpreter import nitc::frontend import nitc::parser_util +intrude import nitc::scope redef class ToolContext @@ -55,21 +58,6 @@ redef class ToolContext return tree.n_base.as(not null) end - # Read an user-line with a given `prompt` - # - # Return `null` if end of file - fun readline(prompt: String): nullable String do - printn prompt - var res = stdin.read_line - if res == "" and stdin.eof then return null - return res - end - - # Add `text` in the history for `readline`. - # - # With the default implementation, the history is dropped - fun readline_add_history(text: String) do end - # The last line number read by `i_parse` var last_line = 0 @@ -84,7 +72,7 @@ redef class ToolContext s = stdin.read_line if s == "" and stdin.eof then s = null else - s = readline(prompt) + s = sys.prompt(prompt) end if s == null then return null if s == "" then @@ -106,7 +94,7 @@ redef class ToolContext oldtext = "" var n = p_module(text) - if n isa AParserError and (n.token isa EOF) then + if n isa AParserError and (n.token isa EOF or n.token isa TBadTString or n.token isa TBadExtern) then # Unexpected end of file, thus continuing if oldtext == "" then prompt = "." * prompt.length oldtext = text @@ -114,12 +102,68 @@ redef class ToolContext end last_line = n.location.file.line_starts.length - 1 - readline_add_history(text.chomp) + prompt_add_history(text.chomp) return n end end end +redef class AMethPropdef + var injected_variables: nullable Map[Variable, Instance] = null is writable + var new_variables: nullable Array[Variable] = null + + redef fun accept_scope_visitor(v) + do + var injected_variables = self.injected_variables + if injected_variables == null then + super + return + end + + # Inject main variables in the initial scope + var scope = v.scopes.first + for variable in injected_variables.keys do + scope.variables[variable.name] = variable + end + + super + + # Gather new top-level variables as main variables + scope = v.scopes.first + var new_variables = new Array[Variable] + for variable in scope.variables.values do + if not injected_variables.has_key(variable) then + new_variables.add(variable) + end + end + self.new_variables = new_variables + end + + redef fun call_commons(v, m, a, f) + do + var injected_variables = self.injected_variables + if injected_variables == null then return super + + # Inject main variables in the frame + assert f isa InterpreterFrame + for variable, i in injected_variables do + f.map[variable] = i + end + + var res = super + + # Update the values of the variables + for variable in injected_variables.keys do + injected_variables[variable] = f.map[variable] + end + # Retrieve the values of the new main variables + for variable in new_variables.as(not null) do + injected_variables[variable] = f.map[variable] + end + + return res + end +end # Create a tool context to handle options and paths var toolcontext = new ToolContext @@ -155,6 +199,8 @@ var sys_type = mainobj.mtype.as(MClassType) var mainprop = mainmodule.try_get_primitive_method("main", sys_type.mclass) assert mainprop != null +var main_variables = new Map[Variable, Instance] + var l = 0 loop # Next piece of Nit code @@ -177,6 +223,7 @@ loop # An error if n isa AError then modelbuilder.error(n, n.message) + toolcontext.check_errors continue end @@ -194,6 +241,7 @@ loop if amodule.n_classdefs.not_empty and amodule.n_classdefs.last isa AMainClassdef then main_method = amodule.n_classdefs.last.n_propdefs.first assert main_method isa AMethPropdef + main_method.injected_variables = main_variables end modelbuilder.run_phases