NITCOPT=
-all: ../bin/nitdoc ../bin/nitmetrics ../bin/nitg ../bin/nit ../bin/nitx ../bin/nitunit ../bin/nitlight ../bin/nitls ../bin/nitdbg_server ../bin/nitdbg_client
+all: ../bin/nitdoc ../bin/nitmetrics ../bin/nitg ../bin/nit ../bin/nitx ../bin/nitunit ../bin/nitlight ../bin/nitls ../bin/nitdbg_client
../bin/nitg: ../c_src/nitg parser/parser.nit
@echo '***************************************************************'
../bin/nitmetrics: ../bin/nitg
@echo '***************************************************************'
- @echo '* Compile nitmetrics from NIT source files *'
+ @echo '* Compile nitmetrics from NIT source files *'
@echo '***************************************************************'
./git-gen-version.sh
../bin/nitg ${NITCOPT} -o ../bin/nitmetrics -v nitmetrics.nit
../bin/nitdbg_client : ../bin/nitg
@echo '***************************************************************'
- @echo '* Compile nitdbg_client from NIT source files *'
+ @echo '* Compile nitdbg_client from NIT source files *'
@echo '***************************************************************'
./git-gen-version.sh
../bin/nitg ${NITCOPT} -o ../bin/nitdbg_client -v nitdbg_client.nit
-../bin/nitdbg_server : ../bin/nitg
- @echo '***************************************************************'
- @echo '* Compile nitdbg_server from NIT source files *'
- @echo '***************************************************************'
- ./git-gen-version.sh
- ../bin/nitg ${NITCOPT} -o ../bin/nitdbg_server -v nitdbg_server.nit
-
../bin/nitx: ../bin/nitg
@echo '***************************************************************'
@echo '* Compile nitx from NIT source files *'
intrude import local_var_init
intrude import scope
intrude import toolcontext
+import websocket
redef class Model
# Cleans the model to remove a module and what it defines when semantic analysis fails on injected code
for m in messages do
if m.text.search("Warning") == null then had_error = true
- stderr.write("{m.to_color_string}\n")
+ sys.stderr.write("{m.to_color_string}\n")
end
end
# -c
var opt_debugger_autorun: OptionBool = new OptionBool("Launches the target program with the interpreter, such as when the program fails, the debugging prompt is summoned", "-c")
+ # --socket
+ var opt_socket_mode = new OptionBool("Launches the target program with raw output on the network via sockets", "--socket")
+
+ # --websocket
+ var opt_websocket_mode = new OptionBool("Launches the target program with output on the network via websockets", "--websocket")
+
+ # --port
+ var opt_debug_port: OptionInt = new OptionInt("Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535", 22125, "--port")
+
redef init
do
super
self.option_context.add_option(self.opt_debugger_mode)
self.option_context.add_option(self.opt_debugger_autorun)
+ self.option_context.add_option(self.opt_socket_mode)
+ self.option_context.add_option(self.opt_websocket_mode)
+ self.option_context.add_option(self.opt_debug_port)
end
end
var interpreter = new Debugger(self, mainmodule, arguments)
+ set_stdstreams
+
init_naive_interpreter(interpreter, mainmodule)
+ close_stdstreams
+
var time1 = get_time
self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
end
var interpreter = new Debugger(self, mainmodule, arguments)
interpreter.autocontinue = true
+ set_stdstreams
+
init_naive_interpreter(interpreter, mainmodule)
+ close_stdstreams
+
var time1 = get_time
self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
end
+
+ redef fun run_naive_interpreter(mmod, args)
+ do
+ set_stdstreams
+ super
+ end
+
+ fun set_stdstreams
+ do
+ if self.toolcontext.opt_socket_mode.value then
+ var sock = new Socket.server(toolcontext.opt_debug_port.value, 1)
+ var ns = sock.accept
+ sock.close
+ sys.set_io(ns,ns,ns)
+ else if self.toolcontext.opt_websocket_mode.value then
+ var websock = new WebSocket(toolcontext.opt_debug_port.value, 1)
+ websock.accept
+ sys.set_io(websock,websock,websock)
+ end
+ end
+
+ fun close_stdstreams
+ do
+ if sys.stdin isa WebSocket or sys.stdin isa Socket then
+ sys.stdin.close
+ sys.stdout.close
+ sys.stderr.close
+ end
+ end
+end
+
+redef class Sys
+ private fun set_io(istream: PollableIStream, ostream: OStream, errstream: OStream)
+ do
+ self.stdin = istream
+ self.stdout = ostream
+ self.stderr = ostream
+ end
end
# The class extending `NaiveInterpreter` by adding debugging methods
var old = frame.current_node
frame.current_node = n
+ if sys.stdin.poll_in then process_debug_command(gets)
+
if not self.autocontinue then
if not n isa ABlockExpr then
steps_fun_call(n)
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2013 Lucas Bajolet <lucas.bajolet@hotmail.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module debugger_commons
-
-import modelbuilder
-import frontend
-import transform
-
-class InterpretCommons
-
- var model: nullable Model
- var modelbuilder: nullable ModelBuilder
- var toolcontext: nullable ToolContext
- var mainmodule: nullable MModule
- var arguments: nullable Array[String]
-
- init
- do
- end
-
- fun launch
- do
- # Create a tool context to handle options and paths
- toolcontext = new ToolContext
- toolcontext.tooldescription = "Usage: nit [OPTION]... <file.nit>...\nInterprets and debbugs Nit programs."
- # Add an option "-o" to enable compatibilit with the tests.sh script
- var opt = new OptionString("compatibility (does noting)", "-o")
- toolcontext.option_context.add_option(opt)
- var opt_mixins = new OptionArray("Additionals module to min-in", "-m")
- toolcontext.option_context.add_option(opt_mixins)
- # We do not add other options, so process them now!
- toolcontext.process_options(args)
-
- # We need a model to collect stufs
- var model = new Model
- self.model = model
- # An a model builder to parse files
- modelbuilder = new ModelBuilder(model, toolcontext.as(not null))
-
- arguments = toolcontext.option_context.rest
- var progname = arguments.first
-
- # Here we load an process all modules passed on the command line
- var mmodules = modelbuilder.parse([progname])
- mmodules.add_all modelbuilder.parse(opt_mixins.value)
- modelbuilder.run_phases
-
- if toolcontext.opt_only_metamodel.value then exit(0)
-
- # Here we launch the interpreter on the main module
- if mmodules.length == 1 then
- mainmodule = mmodules.first
- else
- mainmodule = new MModule(model, null, mmodules.first.name, mmodules.first.location)
- mainmodule.set_imported_mmodules(mmodules)
- end
- end
-
-end
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2013 Lucas Bajolet <lucas.bajolet@gmail.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Network debugger for a nit program, based on the original debugger
-# Replaces access to stdin/stdout to send data on the network to the client concerned
-module network_debugger
-
-import socket
-intrude import debugger
-
-redef class ToolContext
-
- var opt_debug_port: OptionInt = new OptionInt("Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535", 22125, "--port")
-
- redef init
- do
- super
- self.option_context.add_option(self.opt_debug_port)
- end
-
-end
-
-redef class ModelBuilder
- fun run_debugger_network_mode(mainmodule: MModule, arguments: Array[String], port: Int)
- do
- var time0 = get_time
- self.toolcontext.info("*** START INTERPRETING ***", 1)
-
- var interpreter = new NetworkDebugger(self, mainmodule, arguments, port)
-
- init_naive_interpreter(interpreter, mainmodule)
-
- var time1 = get_time
- self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
-
- interpreter.disconnect_routine
-
- interpreter.ns.close
- interpreter.socket.close
- end
-end
-
-# Extends the debugger by adding new network capabilities for remote debugging
-class NetworkDebugger
- super Debugger
-
- # Represents the connexion with a particular client (Actually the only one accepted at the moment)
- private var ns: Socket
-
- # Socket for the server, supposed to listen for incoming request from a client
- private var socket: Socket
-
- # Initializes the debugger, waits for a client to connect
- # Then starts debugging as usual
- init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String], port: Int)
- do
- print "Listening on port {port}"
-
- socket = new Socket.stream_with_port(port)
-
- socket.bind
- socket.listen(1)
-
- ns = socket.accept
-
- socket.close
-
- print "Client connected"
-
- stdin.connection = ns
-
- if stdout isa Stdout then
- (stdout.as(Stdout)).connection = ns
- else
- ns.close
- abort
- end
-
- super
- end
-
- # Provokes the disconnection of the client
- # Used when debugging is over
- fun disconnect_routine
- do
- print "DBG DONE WORK ON SELF"
-
- var cliOverResp = ""
-
- while cliOverResp != "CLIENT DBG DONE ACK" do
- cliOverResp = gets
- end
- end
-
- # Checks on every call if the client has sent a command before continuing debugging
- redef fun stmt(n)
- do
- if stdin.poll_in then
- var command = gets
- if command == "stop" then
- n.debug("Stopped by client")
- while process_debug_command(gets) do end
- else
- process_debug_command(command)
- end
- end
-
- super(n)
- end
-
-end
-
-redef class ANode
-
- # Breaks automatically when encountering an error
- # Permits the injunction of commands before crashing
- # Disconnects from the client before crashing
- redef private fun fatal(v: NaiveInterpreter, message: String)
- do
- if v isa Debugger then
- print "An error was encountered, the program will stop now."
- self.debug(message)
- while v.process_debug_command(gets) do end
- end
-
- if v isa NetworkDebugger then
- v.disconnect_routine
- stdin.connection.close
- end
-
- super
- end
-end
-
-# Replaces Stdin to read on the network
-redef class Stdin
-
- # Represents the connection with a client
- var connection: nullable Socket = null
-
- # Used to store data that has been read from the connection
- var buf: Buffer = new FlatBuffer
- var buf_pos: Int = 0
-
- # Checks if data is available for reading
- redef fun poll_in
- do
- return connection.ready_to_read(0)
- end
-
- # Reads the whole content of the buffer
- # Blocking if the buffer is empty
- redef fun read_all
- do
- var loc_buf = new FlatBuffer
- if connection.ready_to_read(0) then buf.append(connection.read)
- for i in [buf_pos .. buf.length-1] do loc_buf.add(buf.chars[i])
- buf.clear
- buf_pos = 0
- return loc_buf.to_s
- end
-
- # Reads a single char on the incoming buffer
- # If the buffer is empty, the call is blocking
- redef fun read_char
- do
- if connection.ready_to_read(0) then buf.append(connection.read)
- if buf_pos >= buf.length then
- buf.clear
- buf_pos = 0
- #Blocking call
- buf.append(connection.read)
- end
- buf_pos += 1
- return buf.chars[buf_pos-1].ascii
- end
-
- # Reads a line on the network if available
- # Stops at the first encounter of a \n character
- # If the buffer is empty, the read_line call is blocking
- redef fun read_line
- do
- var line_buf = new FlatBuffer
- if connection.ready_to_read(0) then buf.append(connection.read)
- var has_found_eol: Bool = false
- loop
- if buf_pos >= buf.length then
- buf.clear
- buf_pos = 0
- # Blocking call
- buf.append(connection.read)
- end
- buf_pos += 1
- if buf.chars[buf_pos-1] == '\n' then break
- line_buf.add(buf.chars[buf_pos-1])
- end
- return line_buf.to_s
- end
-end
-
-# Replaces Stdout to write on the network
-redef class Stdout
-
- # Connection with the client object
- var connection: nullable Socket = null
-
- # Writes a string on the network if available, else
- # it is written in the standard output (Terminal)
- redef fun write(s)
- do
- if connection != null then
- connection.write(s.to_s)
- else
- super
- end
- end
-
-end
import naive_interpreter
import debugger
-import debugger_commons
-
-redef class InterpretCommons
-
- redef fun launch
- do
- super
- var self_mm = mainmodule.as(not null)
- var self_args = arguments.as(not null)
- if toolcontext.opt_debugger_autorun.value then
- modelbuilder.run_debugger_autorun(self_mm, self_args)
- else if toolcontext.opt_debugger_mode.value then
- modelbuilder.run_debugger(self_mm, self_args)
- else
- modelbuilder.run_naive_interpreter(self_mm, self_args)
- end
- end
+# Create a tool context to handle options and paths
+var toolcontext = new ToolContext
+toolcontext.tooldescription = "Usage: nit [OPTION]... <file.nit>...\nInterprets and debbugs Nit programs."
+# Add an option "-o" to enable compatibilit with the tests.sh script
+var opt = new OptionString("compatibility (does noting)", "-o")
+toolcontext.option_context.add_option(opt)
+var opt_mixins = new OptionArray("Additionals module to min-in", "-m")
+toolcontext.option_context.add_option(opt_mixins)
+# We do not add other options, so process them now!
+toolcontext.process_options(args)
+
+# We need a model to collect stufs
+var model = new Model
+# An a model builder to parse files
+var modelbuilder = new ModelBuilder(model, toolcontext.as(not null))
+
+var arguments = toolcontext.option_context.rest
+var progname = arguments.first
+
+# Here we load an process all modules passed on the command line
+var mmodules = modelbuilder.parse([progname])
+mmodules.add_all modelbuilder.parse(opt_mixins.value)
+modelbuilder.run_phases
+
+if toolcontext.opt_only_metamodel.value then exit(0)
+
+var mainmodule: nullable MModule
+
+# Here we launch the interpreter on the main module
+if mmodules.length == 1 then
+ mainmodule = mmodules.first
+else
+ mainmodule = new MModule(model, null, mmodules.first.name, mmodules.first.location)
+ mainmodule.set_imported_mmodules(mmodules)
+end
+
+var self_mm = mainmodule.as(not null)
+var self_args = arguments.as(not null)
+
+if toolcontext.opt_debugger_autorun.value then
+ modelbuilder.run_debugger_autorun(self_mm, self_args)
+else if toolcontext.opt_debugger_mode.value then
+ modelbuilder.run_debugger(self_mm, self_args)
+else
+ modelbuilder.run_naive_interpreter(self_mm, self_args)
end
-(new InterpretCommons).launch
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2013 Lucas Bajolet <lucas.bajolet@hotmail.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Network debugger for a nit program (server part)
-module nitdbg_server
-
-import network_debugger
-import debugger_commons
-
-redef class InterpretCommons
-
- redef fun launch
- do
- super
- if toolcontext.opt_debug_port.value < 0 or toolcontext.opt_debug_port.value > 65535 then
- toolcontext.option_context.usage
- return
- end
-
- modelbuilder.run_debugger_network_mode(mainmodule.as(not null),arguments.as(not null),toolcontext.opt_debug_port.value)
- end
-
-end
-
-(new InterpretCommons).launch
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2014 Lucas Bajolet <r4pass@hotmail.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Network debugger for a nit program (server part)
-module nitdbg_websocket_server
-
-import websocket_debugger
-import debugger_commons
-
-redef class InterpretCommons
-
- redef fun launch
- do
- super
- if toolcontext.opt_debug_port.value < 0 or toolcontext.opt_debug_port.value > 65535 then
- toolcontext.option_context.usage
- return
- end
-
- modelbuilder.run_debugger_network_mode(mainmodule.as(not null),arguments.as(not null),toolcontext.opt_debug_port.value)
- end
-
-end
-
-(new InterpretCommons).launch
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2014 Lucas Bajolet <r4pass@hotmail.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Network debugger for a nit program, based on the original debugger
-# Replaces access to stdin/stdout to send data on the network to the client concerned
-module websocket_debugger
-
-import websocket
-intrude import debugger
-
-redef class ToolContext
-
- var opt_debug_port: OptionInt = new OptionInt("Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535", 22125, "--port")
-
- redef init
- do
- super
- self.option_context.add_option(self.opt_debug_port)
- end
-
-end
-
-redef class ModelBuilder
- fun run_debugger_network_mode(mainmodule: MModule, arguments: Array[String], port: Int)
- do
- var time0 = get_time
- self.toolcontext.info("*** START INTERPRETING ***", 1)
-
- var interpreter = new NetworkDebugger(self, mainmodule, arguments, port)
-
- init_naive_interpreter(interpreter, mainmodule)
-
- var time1 = get_time
- self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
-
- interpreter.ns.stop_server
- end
-end
-
-# Extends the debugger by adding new network capabilities for remote debugging
-class NetworkDebugger
- super Debugger
-
- # Represents the connexion with a particular client (Actually the only one accepted at the moment)
- private var ns: WebSocket
-
- # Initializes the debugger, waits for a client to connect
- # Then starts debugging as usual
- init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String], port: Int)
- do
- print "Listening on port {port}"
-
- ns = new WebSocket(port, 1)
-
- ns.accept
-
- print "Client connected"
-
- stdin.connection = ns
-
- if stdout isa Stdout then
- (stdout.as(Stdout)).connection = ns
- else
- ns.stop_server
- abort
- end
-
- super
- end
-
- # Checks on every call if the client has sent a command before continuing debugging
- redef fun stmt(n)
- do
- if stdin.poll_in then
- var command = gets
- if command == "stop" then
- n.debug("Stopped by client")
- while process_debug_command(gets) do end
- else
- process_debug_command(command)
- end
- end
-
- super(n)
- end
-
-end
-
-redef class ANode
-
- # Breaks automatically when encountering an error
- # Permits the injunction of commands before crashing
- # Disconnects from the client before crashing
- redef private fun fatal(v: NaiveInterpreter, message: String)
- do
- if v isa Debugger then
- print "An error was encountered, the program will stop now."
- self.debug(message)
- while v.process_debug_command(gets) do end
- end
-
- if v isa NetworkDebugger then
- stdin.connection.stop_server
- end
-
- super
- end
-end
-
-# Replaces Stdin to read on the network
-redef class Stdin
-
- # Represents the connection with a client
- var connection: nullable WebSocket = null
-
- # Used to store data that has been read from the connection
- var buf: Buffer = new FlatBuffer
- var buf_pos: Int = 0
-
- # Checks if data is available for reading
- redef fun poll_in
- do
- return connection.can_read(0)
- end
-
- # Reads the whole content of the buffer
- # Blocking if the buffer is empty
- redef fun read_all
- do
- var loc_buf = new FlatBuffer
- if connection.can_read(0) then buf.append(connection.read)
- for i in [buf_pos .. buf.length-1] do loc_buf.add(buf.chars[i])
- buf.clear
- buf_pos = 0
- return loc_buf.to_s
- end
-
- # Reads a single char on the incoming buffer
- # If the buffer is empty, the call is blocking
- redef fun read_char
- do
- if connection.can_read(0) then buf.append(connection.read)
- if buf_pos >= buf.length then
- buf.clear
- buf_pos = 0
- #Blocking call
- buf.append(connection.read)
- end
- buf_pos += 1
- return buf.chars[buf_pos-1].ascii
- end
-
- # Reads a line on the network if available
- # Stops at the first encounter of a \n character
- # If the buffer is empty, the read_line call is blocking
- redef fun read_line
- do
- var line_buf = new FlatBuffer
- if connection.can_read(0) then
- buf.append(connection.read)
- end
- var has_found_eol: Bool = false
- loop
- if buf_pos >= buf.length then
- buf.clear
- buf_pos = 0
- # Blocking call
- buf.append(connection.read)
- end
- buf_pos += 1
- if buf.chars[buf_pos-1] == '\n' then break
- line_buf.add(buf.chars[buf_pos-1])
- end
- return line_buf.to_s
- end
-end
-
-# Replaces Stdout to write on the network
-redef class Stdout
-
- # Connection with the client object
- var connection: nullable WebSocket = null
-
- # Writes a string on the network if available, else
- # it is written in the standard output (Terminal)
- redef fun write(s)
- do
- if connection != null then
- connection.write(s.to_s)
- else
- super
- end
- end
-
-end
-