@@ -3,6 +3,7 @@ package novah.cli.repl
33import novah.data.Err
44import novah.data.Ok
55import novah.data.Result
6+ import novah.frontend.error.CompilerProblem
67import novah.main.*
78import java.io.File
89import java.io.IOException
@@ -12,14 +13,15 @@ import kotlin.io.path.Path
1213
1314class Backend (
1415 private val echo : (String ) -> Unit ,
15- private val classpath : String ,
16- private val sourcepath : String ,
16+ private val classpath : String? ,
17+ private val sourcepath : String? ,
1718 output : String
1819) {
1920
2021 private var imports = LinkedList <String >()
2122 private var code = LinkedList <String >()
2223 private var eval = " ()"
24+ private var replType: String? = " "
2325
2426 private val folder = File (output)
2527 private val options = Options (verbose = false , devMode = true )
@@ -37,16 +39,18 @@ class Backend(
3739 private fun clear () {
3840 imports.clear()
3941 code.clear()
42+ eval = " ()"
4043 }
4144
4245 fun help () = """
43- :help -> shows this help
44- :clear -> resets the repl
45- :q -> quits the repl
46- :> -> starts a definition (value or function). Won't stop until an empty new line is reached
47- :test <suite> -> runs the specified test suite using novah.test.runTests
46+ :help -> shows this help
47+ :clear -> resets the repl
48+ :q, ctrl+c -> quits the repl
49+ :> -> starts a definition. Won't stop until an empty new line is reached
50+ :test <suite> -> runs the specified test suite using novah.test.runTests
51+ :t, :type <exp> -> shows the type of the given expression
4852 import <module> -> adds an import to the repl
49- <expression> -> evaluates the expression
53+ <expression> -> evaluates the expression
5054 """ .trimIndent()
5155
5256 fun execute (input : String , def : Boolean = false) {
@@ -67,13 +71,20 @@ class Backend(
6771 echo(res.err)
6872 }
6973 }
70- } else if (input.startsWith(" :test" )) {
74+ } else if (input.startsWith(" :test " )) {
7175 val suite = input.replace(Regex (" ^:test\\ s+" ), " " )
7276 eval = " runTests [$suite ]"
7377 when (val res = build()) {
7478 is Ok -> run ()
7579 is Err -> echo(res.err)
7680 }
81+ } else if (input.startsWith(" :type " ) || input.startsWith(" :t " )) {
82+ val exp = input.replace(Regex (" ^:t\\ w*\\ s+" ), " " )
83+ eval = exp
84+ when (val res = build()) {
85+ is Ok -> echo(" $exp : $replType " )
86+ is Err -> echo(res.err)
87+ }
7788 } else if (input.startsWith(" :" )) {
7889 echo(" error: invalid command `$input `" )
7990 } else if (def) {
@@ -99,37 +110,39 @@ class Backend(
99110 }
100111
101112 private fun build (): Result <FullModuleEnv , String > {
102- val scode = """ module repl1
113+ val scode = """ module _repl1
103114 |
104115 |${imports.joinToString(" \n\n " )}
105116 |
106117 |${code.joinToString(" \n\n " )}
107118 |
119+ |_repl_res = $eval
120+ |
108121 |pub
109122 |main : Array String -> Unit
110- |main _ =
111- | let _res = $eval
112- | println _res
123+ |main _ = println _repl_res
113124 """ .trimMargin()
114125
115- val sources = sequenceOf(Source .SString (Path (" repl1 " ), scode))
126+ val sources = sequenceOf(Source .SString (Path (" _repl1 " ), scode))
116127 val env = Environment (classpath, sourcepath, options)
117128 return try {
118129 env.parseSources(sources)
119130 env.generateCode(folder)
120131
121- val errs = env.errors().filter { it.isErrorOrFatal() }
132+ val errs = env.errors().filter(::errFilter)
122133 if (errs.isNotEmpty()) {
123134 Err (errs.joinToString(" \n\n " ) { it.msg })
124135 } else {
125- Ok (env.modules()[" repl1" ]!! )
136+ val environment = env.modules()[" _repl1" ]!!
137+ replType = environment.env.decls[" _repl_res" ]?.type?.show(typeVarsMap = environment.typeVarsMap)
138+ Ok (environment)
126139 }
127140 } catch (_: CompilationError ) {
128- env.errors().filter { it.isErrorOrFatal() } .joinToString(" \n\n " ) { it.msg }.let { Err (it) }
141+ env.errors().filter(::errFilter) .joinToString(" \n\n " ) { it.msg }.let { Err (it) }
129142 }
130143 }
131144
132- val pbuilder = ProcessBuilder (" java" , " -cp" , " ." , " repl1 .\$ Module" )
145+ private val pbuilder = ProcessBuilder (" java" , " -cp" , " ." , " _repl1 .\$ Module" )
133146 .directory(folder)
134147 .redirectOutput(ProcessBuilder .Redirect .INHERIT )
135148 .redirectError(ProcessBuilder .Redirect .INHERIT )
@@ -144,4 +157,9 @@ class Backend(
144157 1
145158 }
146159 }
160+
161+ companion object {
162+ private fun errFilter (err : CompilerProblem ): Boolean =
163+ err.isErrorOrFatal() && err.msg != " Undefined variable _repl_res."
164+ }
147165}
0 commit comments