1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
19 # The Nit interactive interpreter
22 import nitc
::interpreter
24 import nitc
::parser_util
26 redef class ToolContext
29 var opt_no_prompt
= new OptionBool("Disable writing a prompt.", "--no-prompt")
33 option_context
.add_option
(opt_no_prompt
)
36 # Parse a full module given as a string
38 # Return a AModule or a AError
39 fun p_module
(string
: String): ANode
41 var source
= new SourceFile.from_string
("", string
)
42 var lexer
= new Lexer(source
)
43 var parser
= new Parser(lexer
)
44 var tree
= parser
.parse
47 if eof
isa AError then
50 return tree
.n_base
.as(not null)
53 # Read an user-line with a given `prompt`
55 # Return `null` if end of file
56 fun readline
(prompt
: String): nullable String do
58 var res
= stdin
.read_line
59 if res
== "" and stdin
.eof
then return null
63 # Add `text` in the history for `readline`.
65 # With the default implementation, the history is dropped
66 fun readline_add_history
(text
: String) do end
68 # Parse the input of the user as a module
69 fun i_parse
(prompt
: String): nullable ANode
75 if opt_no_prompt
.value
then
77 if s
== "" and stdin
.eof
then s
= null
81 if s
== null then return null
82 if s
== "" then continue
84 if s
.chars
.first
== ':' then
90 var text
= oldtext
+ s
+ "\n"
92 var n
= p_module
(text
)
94 if n
isa AParserError and (n
.token
isa EOF) then
95 # Unexpected end of file, thus continuing
96 if oldtext
== "" then prompt
= "." * prompt
.length
101 readline_add_history
(text
.chomp
)
108 # Create a tool context to handle options and paths
109 var toolcontext
= new ToolContext
110 toolcontext
.option_context
.options_before_rest
= true
111 toolcontext
.accept_no_arguments
= true
112 toolcontext
.keep_going
= true
113 toolcontext
.process_options
(args
)
115 # We need a model to collect stufs
116 var model
= new Model
117 # An a model builder to parse files
118 var modelbuilder
= new ModelBuilder(model
, toolcontext
)
120 var arguments
= toolcontext
.option_context
.rest
122 # Our initial program is an empty module
123 var amodule
= toolcontext
.parse_module
("")
124 var mmodule
= modelbuilder
.load_rt_module
(null, amodule
, "input-0")
125 modelbuilder
.run_phases
126 if not toolcontext
.check_errors
then return
127 assert mmodule
!= null
128 var mmodules
= [mmodule
]
129 var mainmodule
= toolcontext
.make_main_module
(mmodules
)
131 # Start and run the interpreter on the empty module
132 var interpreter
= new NaiveInterpreter(modelbuilder
, mainmodule
, arguments
)
133 interpreter
.start
(mainmodule
)
135 # Get the main object and the main method
136 var mainobj
= interpreter
.mainobj
137 assert mainobj
!= null
138 var sys_type
= mainobj
.mtype
.as(MClassType)
139 var mainprop
= mainmodule
.try_get_primitive_method
("main", sys_type
.mclass
)
140 assert mainprop
!= null
144 # Next piece of Nit code
145 var n
= toolcontext
.i_parse
("-->")
150 # Special adhoc command
151 if n
isa TString then
163 print
"{n.location.colored_line("0;31")}: {n.message}"
169 # A syntactically module!
170 amodule
= n
.as(AModule)
172 # Try to load it as a submodule
174 var newmodule
= modelbuilder
.load_rt_module
(mainmodule
, amodule
, "input-{l}")
175 if newmodule
== null then continue
176 modelbuilder
.run_phases
177 if not toolcontext
.check_errors
then
178 toolcontext
.error_count
= 0
181 # Everything is fine, the module is the new main module!
182 mainmodule
= newmodule
183 interpreter
.mainmodule
= mainmodule
185 # Run the main if the AST contains a main
186 if amodule
.n_classdefs
.not_empty
and amodule
.n_classdefs
.last
isa AMainClassdef then
187 interpreter
.send
(mainprop
, [mainobj
])