[Bootstrap] Implement a call stack to keep track of function calls
Add `ICallStack` as the interface to the call stack with a simple FIFO implementation that tracks the recursive calls as well.
This commit is contained in:
parent
9dfe54a573
commit
1447f8ac45
|
@ -29,7 +29,7 @@ var replCmd = &cobra.Command{
|
|||
Long: `Runs the local Serene's REPL to interact with Serene`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// TODO: Get the debug value from a CLI flag
|
||||
core.REPL(debugMode)
|
||||
core.REPL(makeFlags())
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,14 @@ import (
|
|||
)
|
||||
|
||||
var debugMode bool
|
||||
var stackDebugMode bool
|
||||
|
||||
func makeFlags() map[string]bool {
|
||||
return map[string]bool{
|
||||
"debugMode": debugMode,
|
||||
"stackDebugMode": stackDebugMode,
|
||||
}
|
||||
}
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
|
@ -62,4 +70,10 @@ func init() {
|
|||
false,
|
||||
"Turns on the debug mode.")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(
|
||||
&stackDebugMode,
|
||||
"debug-stack",
|
||||
false,
|
||||
"Turns on the call stack debug mode.")
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ var runCmd = &cobra.Command{
|
|||
Short: "Evaluates the given NS and runs the main function of it",
|
||||
Long: `Evaluates the given NS and runs the main function`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
core.Run(debugMode, args)
|
||||
core.Run(makeFlags(), args)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -55,13 +55,13 @@ Replace the readline implementation with go-prompt.
|
|||
|
||||
// REPL executes a Read Eval Print Loop locally reading from stdin and
|
||||
// writing to stdout
|
||||
func REPL(debug bool) {
|
||||
func REPL(flags map[string]bool) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rt := MakeRuntime([]string{cwd}, debug)
|
||||
rt := MakeRuntime([]string{cwd}, flags)
|
||||
|
||||
rt.CreateNS("user", "REPL", true)
|
||||
|
||||
|
@ -105,13 +105,13 @@ for details take a look at the LICENSE file.
|
|||
|
||||
}
|
||||
|
||||
func Run(debug bool, args []string) {
|
||||
func Run(flags map[string]bool, args []string) {
|
||||
cwd, e := os.Getwd()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
|
||||
rt := MakeRuntime([]string{cwd}, debug)
|
||||
rt := MakeRuntime([]string{cwd}, flags)
|
||||
|
||||
if len(args) == 0 {
|
||||
|
||||
|
@ -171,10 +171,16 @@ func Run(debug bool, args []string) {
|
|||
}
|
||||
}
|
||||
|
||||
//rt.Stack.Push(mainFn)
|
||||
_, err = mainFn.Apply(rt, loadedNS.GetRootScope(), mainFn.Node, MakeList(fnArgs))
|
||||
|
||||
if err != nil {
|
||||
PrintError(rt, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// rt.Stack.Pop()
|
||||
// if rt.Stack.Count() != 0 {
|
||||
// panic("Call stack is not empty.")
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ func evalForm(rt *Runtime, scope IScope, form IExpr) (IExpr, IError) {
|
|||
switch form.GetType() {
|
||||
case ast.Nil:
|
||||
return form, nil
|
||||
|
||||
case ast.Number:
|
||||
return form, nil
|
||||
|
||||
|
@ -195,7 +196,19 @@ tco:
|
|||
|
||||
if rt.IsDebugMode() {
|
||||
fmt.Printf("[DEBUG] Evaluating forms in NS: %s, Forms: %s\n", rt.CurrentNS().GetName(), forms)
|
||||
fmt.Printf("[DEBUG] -> State: I: %d, Exprs: %s\n", i, exprs)
|
||||
fmt.Printf("[DEBUG] * State: I: %d, Exprs: %s\n", i, exprs)
|
||||
}
|
||||
|
||||
// Evaluate any internal instruction that has to be run.
|
||||
// Instructions should change the return value, but errors
|
||||
// are ok
|
||||
if forms.GetType() == ast.Instruction {
|
||||
err := ProcessInstruction(rt, forms.(*Instruction))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Evaluating forms one by one
|
||||
|
@ -533,7 +546,8 @@ tco:
|
|||
break body //return
|
||||
}
|
||||
|
||||
body := fn.GetBody().ToSlice()
|
||||
rt.Stack.Push(fn)
|
||||
body := append(fn.GetBody().ToSlice(), MakeStackPop(rt))
|
||||
changeExecutionScope(body, fnScope)
|
||||
exprs = append(body, restOfExprs(exprs, i)...)
|
||||
goto body // rewrite
|
||||
|
@ -542,12 +556,14 @@ tco:
|
|||
// by the `NativeFunction` struct
|
||||
case ast.NativeFn:
|
||||
fn := f.(*NativeFunction)
|
||||
rt.Stack.Push(fn)
|
||||
ret, err = fn.Apply(
|
||||
rt,
|
||||
scope,
|
||||
MakeNodeFromExpr(fn),
|
||||
listExprs.(*List),
|
||||
)
|
||||
rt.Stack.Pop()
|
||||
continue body // no rewrite
|
||||
|
||||
default:
|
||||
|
|
|
@ -30,7 +30,7 @@ package core
|
|||
// arguments names
|
||||
// - Evaluate the body of the function in context of the new scope and return
|
||||
// the result of the last expression
|
||||
// * Native functions evaluates by calling the `Apply` method of the `INativeFn`
|
||||
// * Native functions evaluates by calling the `Apply` method of the `IFn`
|
||||
// interface which is quite simple.
|
||||
//
|
||||
// TODOs:
|
||||
|
@ -47,7 +47,8 @@ import (
|
|||
|
||||
type nativeFnHandler = func(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError)
|
||||
|
||||
type INativeFn interface {
|
||||
type IFn interface {
|
||||
ast.ILocatable
|
||||
Apply(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError)
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ type Runtime struct {
|
|||
// languages
|
||||
paths []string
|
||||
|
||||
Stack CallStack
|
||||
// A to turn on the verbose mode, FOR DEVELOPMENT USE ONLY
|
||||
debugMode bool
|
||||
}
|
||||
|
@ -201,12 +202,13 @@ func (r *Runtime) LookupBuiltin(k string) IExpr {
|
|||
// MakeRuntime creates a Runtime and returns a pointer to it. Any
|
||||
// runtime initialization such as adding default namespaces and vice
|
||||
// versa has to happen here.
|
||||
func MakeRuntime(paths []string, debug bool) *Runtime {
|
||||
func MakeRuntime(paths []string, flags map[string]bool) *Runtime {
|
||||
rt := Runtime{
|
||||
namespaces: map[string]Namespace{},
|
||||
currentNS: "",
|
||||
debugMode: debug,
|
||||
debugMode: flags["debugMode"],
|
||||
paths: paths,
|
||||
Stack: MakeCallStack(flags["stackDebugMode"]),
|
||||
}
|
||||
|
||||
rt.builtins = BUILTINS
|
||||
|
|
Loading…
Reference in New Issue