[Bootstrap] Use Serene itself to load and run the main function
This commit consist a series of fixes to make the reach the main goal of the commit: * Fix the 'MakeNodeFromExprs' behavior so it returns a pointer to a node and if the number of input exprs is zero then nil. * Fix all the eval loop to return immediately in case of any error duh! * Add a `errtype` field to `Error` with an `ErrType` enum type that indicates the type of the error, the type being syntax, semantic and runtime error at the moment. * Rename some of the Error functions to match the error type. For Exapmle `MakeSyntaxError` and `MakeSemanticError`
This commit is contained in:
parent
e895377811
commit
9be27c124a
|
@ -20,15 +20,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/chzyer/readline"
|
"github.com/chzyer/readline"
|
||||||
"serene-lang.org/bootstrap/pkg/ast"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type mainRunner struct {
|
||||||
|
NS string
|
||||||
|
Args string
|
||||||
|
}
|
||||||
|
|
||||||
func rep(rt *Runtime, line string) {
|
func rep(rt *Runtime, line string) {
|
||||||
ast, err := ReadString("*REPL*", line)
|
ast, err := ReadString("*REPL*", line)
|
||||||
|
|
||||||
|
@ -113,6 +118,7 @@ func Run(flags map[string]bool, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rt := MakeRuntime([]string{cwd}, flags)
|
rt := MakeRuntime([]string{cwd}, flags)
|
||||||
|
rt.CreateNS("user", "REPL", true)
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|
||||||
|
@ -120,77 +126,51 @@ func Run(flags map[string]bool, args []string) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
arguments := ""
|
||||||
ns := args[0]
|
ns := args[0]
|
||||||
nsAsBuffer := strings.Split(ns, "")
|
|
||||||
source := &ast.Source{Buffer: &nsAsBuffer, Path: "*input-argument*"}
|
|
||||||
node := MakeNode(source, 0, len(ns))
|
|
||||||
nsSym, err := MakeSymbol(node, ns)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
PrintError(rt, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadedNS, err := requireNS(rt, nsSym)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
PrintError(rt, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rt.InsertNS(ns, loadedNS)
|
|
||||||
inserted := rt.setCurrentNS(loadedNS.GetName())
|
|
||||||
|
|
||||||
if !inserted {
|
|
||||||
err := MakeError(
|
|
||||||
rt,
|
|
||||||
loadedNS,
|
|
||||||
fmt.Sprintf(
|
|
||||||
"the namespace '%s' didn't get inserted in the runtime.",
|
|
||||||
loadedNS.GetName()),
|
|
||||||
)
|
|
||||||
PrintError(rt, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluating the body of the loaded ns (Check for ns validation happens here)
|
|
||||||
loadedNS, err = EvalNSBody(rt, loadedNS)
|
|
||||||
if err != nil {
|
|
||||||
PrintError(rt, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
mainBinding := loadedNS.GetRootScope().Lookup(rt, "main")
|
|
||||||
|
|
||||||
if mainBinding == nil {
|
|
||||||
PrintError(rt, MakePlainError(fmt.Sprintf("can't find the 'main' function in '%s' namespace", ns)))
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mainBinding.Value.GetType() != ast.Fn {
|
|
||||||
PrintError(rt, MakePlainError("'main' is not a function"))
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
mainFn := mainBinding.Value.(*Function)
|
|
||||||
|
|
||||||
var fnArgs []IExpr
|
|
||||||
var argNode Node
|
|
||||||
|
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
for _, arg := range args[1:] {
|
for _, arg := range args[1:] {
|
||||||
node := MakeNodeFromExpr(mainFn)
|
arguments += "\"" + arg + "\""
|
||||||
fnArgs = append(fnArgs, MakeString(node, arg))
|
|
||||||
}
|
}
|
||||||
argNode = MakeNodeFromExprs(fnArgs)
|
|
||||||
} else {
|
|
||||||
argNode = node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = mainFn.Apply(rt, loadedNS.GetRootScope(), mainFn.Node, MakeList(argNode, fnArgs))
|
tmpl, e := template.New("run").Parse(
|
||||||
|
`(def run-main
|
||||||
|
(fn ()
|
||||||
|
(require '({{.NS}} n))
|
||||||
|
(n/main {{.Args}})))
|
||||||
|
|
||||||
|
(run-main)`,
|
||||||
|
)
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
e = tmpl.Execute(&buf, &mainRunner{ns, arguments})
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rt.IsDebugMode() {
|
||||||
|
fmt.Println("[DEBUG] Evaluating the following form to run the 'main' fn:")
|
||||||
|
fmt.Println(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
ast, err := ReadString("*RUN*", buf.String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
PrintError(rt, err)
|
PrintError(rt, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = Eval(rt, ast)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
PrintError(rt, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,14 @@ import (
|
||||||
"serene-lang.org/bootstrap/pkg/errors"
|
"serene-lang.org/bootstrap/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ErrType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
SyntaxError ErrType = iota
|
||||||
|
SemanticError
|
||||||
|
RuntimeError
|
||||||
|
)
|
||||||
|
|
||||||
// IError defines the necessary functionality of the internal errors.
|
// IError defines the necessary functionality of the internal errors.
|
||||||
type IError interface {
|
type IError interface {
|
||||||
// In order to point to a specific point in the input
|
// In order to point to a specific point in the input
|
||||||
|
@ -50,6 +58,7 @@ type IError interface {
|
||||||
IRepresentable
|
IRepresentable
|
||||||
IDebuggable
|
IDebuggable
|
||||||
|
|
||||||
|
GetErrType() ErrType
|
||||||
GetDescription() *string
|
GetDescription() *string
|
||||||
GetStackTrace() *TraceBack
|
GetStackTrace() *TraceBack
|
||||||
// To wrap Golan rrrrors
|
// To wrap Golan rrrrors
|
||||||
|
@ -63,6 +72,7 @@ type IError interface {
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Node
|
Node
|
||||||
|
errtype ErrType
|
||||||
errno errors.Errno
|
errno errors.Errno
|
||||||
WrappedErr error
|
WrappedErr error
|
||||||
msg string
|
msg string
|
||||||
|
@ -81,6 +91,10 @@ func (e *Error) ToDebugStr() string {
|
||||||
return fmt.Sprintf("%s:\n\t%s", e.msg, e.WrappedErr.Error())
|
return fmt.Sprintf("%s:\n\t%s", e.msg, e.WrappedErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Error) GetErrType() ErrType {
|
||||||
|
return e.errtype
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Error) WithError(err error) IError {
|
func (e *Error) WithError(err error) IError {
|
||||||
e.WrappedErr = err
|
e.WrappedErr = err
|
||||||
return e
|
return e
|
||||||
|
@ -117,19 +131,22 @@ func MakePlainError(msg string) IError {
|
||||||
// MakeError creates an Error which points to the given IExpr `e` as
|
// MakeError creates an Error which points to the given IExpr `e` as
|
||||||
// the root of the error.
|
// the root of the error.
|
||||||
func MakeError(rt *Runtime, e IExpr, msg string) IError {
|
func MakeError(rt *Runtime, e IExpr, msg string) IError {
|
||||||
trace := append(*rt.Stack.ToTraceBack(), &Frame{0, rt.Stack.GetCurrentFn(), e})
|
frame := MakeFrame(e, rt.Stack.GetCurrentFn(), 1)
|
||||||
|
trace := append(*rt.Stack.ToTraceBack(), frame)
|
||||||
|
|
||||||
return &Error{
|
return &Error{
|
||||||
Node: MakeNodeFromExpr(e),
|
Node: MakeNodeFromExpr(e),
|
||||||
msg: msg,
|
errtype: RuntimeError,
|
||||||
trace: &trace,
|
msg: msg,
|
||||||
|
trace: &trace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeParsetimeErrorf(n Node, msg string, a ...interface{}) IError {
|
func MakeSyntaxErrorf(n Node, msg string, a ...interface{}) IError {
|
||||||
return &Error{
|
return &Error{
|
||||||
Node: n,
|
Node: n,
|
||||||
msg: fmt.Sprintf(msg, a...),
|
errtype: SyntaxError,
|
||||||
|
msg: fmt.Sprintf(msg, a...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +158,10 @@ func MakeSemanticError(rt *Runtime, e IExpr, errno errors.Errno, msg string) IEr
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Error{
|
return &Error{
|
||||||
Node: MakeNodeFromExpr(e),
|
Node: MakeNodeFromExpr(e),
|
||||||
errno: errno,
|
errtype: SemanticError,
|
||||||
msg: msg,
|
errno: errno,
|
||||||
trace: frames,
|
msg: msg,
|
||||||
|
trace: frames,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,6 +218,10 @@ tco:
|
||||||
// Evaluating forms one by one
|
// Evaluating forms one by one
|
||||||
if forms.GetType() != ast.List {
|
if forms.GetType() != ast.List {
|
||||||
ret, err = evalForm(rt, scope, forms)
|
ret, err = evalForm(rt, scope, forms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body
|
continue body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +275,10 @@ tco:
|
||||||
// TODO: decide on the syntax and complete the docs
|
// TODO: decide on the syntax and complete the docs
|
||||||
case "ns":
|
case "ns":
|
||||||
ret, err = NSForm(rt, scope, list)
|
ret, err = NSForm(rt, scope, list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `quote` evaluation rules:
|
// `quote` evaluation rules:
|
||||||
|
@ -298,6 +306,10 @@ tco:
|
||||||
// Creates a new list form it's arguments.
|
// Creates a new list form it's arguments.
|
||||||
case "list":
|
case "list":
|
||||||
ret, err = evalForm(rt, scope, list.Rest().(*List))
|
ret, err = evalForm(rt, scope, list.Rest().(*List))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// TODO: Implement `concat` in serene itself when we have protocols available
|
// TODO: Implement `concat` in serene itself when we have protocols available
|
||||||
|
@ -320,12 +332,19 @@ tco:
|
||||||
result = append(result, lst.(*List).ToSlice()...)
|
result = append(result, lst.(*List).ToSlice()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
node := MakeNodeFromExpr(list)
|
n := MakeNodeFromExprs(result)
|
||||||
if len(result) > 0 {
|
|
||||||
node = MakeNodeFromExprs(result)
|
if n == nil {
|
||||||
|
n = &list.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node := *n
|
||||||
|
|
||||||
ret, err = MakeList(node, result), nil
|
ret, err = MakeList(node, result), nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// TODO: Implement `list` in serene itself when we have destructuring available
|
// TODO: Implement `list` in serene itself when we have destructuring available
|
||||||
|
@ -349,6 +368,10 @@ tco:
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err = coll.Cons(evaledForms.(*List).First()), nil
|
ret, err = coll.Cons(evaledForms.(*List).First()), nil
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `def` evaluation rules
|
// `def` evaluation rules
|
||||||
|
@ -359,6 +382,10 @@ tco:
|
||||||
// the symbol name binded to the value
|
// the symbol name binded to the value
|
||||||
case "def":
|
case "def":
|
||||||
ret, err = Def(rt, scope, list.Rest().(*List))
|
ret, err = Def(rt, scope, list.Rest().(*List))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `defmacro` evaluation rules:
|
// `defmacro` evaluation rules:
|
||||||
|
@ -368,6 +395,10 @@ tco:
|
||||||
// body of the macro.
|
// body of the macro.
|
||||||
case "defmacro":
|
case "defmacro":
|
||||||
ret, err = DefMacro(rt, scope, list.Rest().(*List))
|
ret, err = DefMacro(rt, scope, list.Rest().(*List))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `macroexpand` evaluation rules:
|
// `macroexpand` evaluation rules:
|
||||||
|
@ -385,6 +416,9 @@ tco:
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err = macroexpand(rt, scope, evaledForm.(*List).First())
|
ret, err = macroexpand(rt, scope, evaledForm.(*List).First())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `fn` evaluation rules:
|
// `fn` evaluation rules:
|
||||||
|
@ -392,6 +426,9 @@ tco:
|
||||||
// * Defines an anonymous function.
|
// * Defines an anonymous function.
|
||||||
case "fn":
|
case "fn":
|
||||||
ret, err = Fn(rt, scope, list)
|
ret, err = Fn(rt, scope, list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `if` evaluation rules:
|
// `if` evaluation rules:
|
||||||
|
@ -454,6 +491,10 @@ tco:
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err = EvalForms(rt, scope, form)
|
ret, err = EvalForms(rt, scope, form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
// `let` evaluation rules:
|
// `let` evaluation rules:
|
||||||
|
@ -525,9 +566,7 @@ tco:
|
||||||
// Evaluating all the elements of the list
|
// Evaluating all the elements of the list
|
||||||
listExprs, e := evalForm(rt, scope, list)
|
listExprs, e := evalForm(rt, scope, list)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err = e
|
return nil, e
|
||||||
ret = nil
|
|
||||||
break tco //return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f := listExprs.(*List).First()
|
f := listExprs.(*List).First()
|
||||||
|
@ -541,19 +580,14 @@ tco:
|
||||||
// `expressions` to the body of function and loop again
|
// `expressions` to the body of function and loop again
|
||||||
fn := f.(*Function)
|
fn := f.(*Function)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err = e
|
return nil, e
|
||||||
ret = nil
|
|
||||||
break body //return
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
argList := listExprs.(*List).Rest().(*List)
|
argList := listExprs.(*List).Rest().(*List)
|
||||||
|
|
||||||
fnScope, e := MakeFnScope(rt, fn.GetScope(), fn.GetParams(), argList)
|
fnScope, e := MakeFnScope(rt, fn.GetScope(), fn.GetParams(), argList)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err = e
|
return nil, e
|
||||||
ret = nil
|
|
||||||
break body //return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.Stack.Push(list, fn)
|
rt.Stack.Push(list, fn)
|
||||||
|
@ -579,6 +613,11 @@ tco:
|
||||||
MakeNodeFromExpr(fn),
|
MakeNodeFromExpr(fn),
|
||||||
listExprs.(*List),
|
listExprs.(*List),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
rt.Stack.Pop()
|
rt.Stack.Pop()
|
||||||
continue body // no rewrite
|
continue body // no rewrite
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,13 @@ func MakeFnScope(rt *Runtime, parent IScope, bindings IColl, values IColl) (*Sco
|
||||||
var node Node
|
var node Node
|
||||||
|
|
||||||
if len(elements) > 0 {
|
if len(elements) > 0 {
|
||||||
node = MakeNodeFromExprs(elements)
|
n := MakeNodeFromExprs(elements)
|
||||||
|
|
||||||
|
if n == nil {
|
||||||
|
n = &values.(*List).Node
|
||||||
|
}
|
||||||
|
|
||||||
|
node = *n
|
||||||
} else {
|
} else {
|
||||||
node = MakeNodeFromExpr(binds[i])
|
node = MakeNodeFromExpr(binds[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,11 +181,11 @@ func extractParts(s string) (string, string) {
|
||||||
|
|
||||||
func MakeKeyword(n Node, name string) (*Keyword, IError) {
|
func MakeKeyword(n Node, name string) (*Keyword, IError) {
|
||||||
if strings.Count(name, ":") > 2 {
|
if strings.Count(name, ":") > 2 {
|
||||||
return nil, MakeParsetimeErrorf(n, "can't parse the keyword with more that two colons: '%s'", name)
|
return nil, MakeSyntaxErrorf(n, "can't parse the keyword with more that two colons: '%s'", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Count(name, "/") > 1 {
|
if strings.Count(name, "/") > 1 {
|
||||||
return nil, MakeParsetimeErrorf(n, "illegal namespace path for the given keyword: '%s'", name)
|
return nil, MakeSyntaxErrorf(n, "illegal namespace path for the given keyword: '%s'", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var nsName string
|
var nsName string
|
||||||
|
|
|
@ -76,7 +76,12 @@ func (l *List) Rest() ISeq {
|
||||||
rest := l.exprs[1:]
|
rest := l.exprs[1:]
|
||||||
node := l.Node
|
node := l.Node
|
||||||
if len(rest) > 0 {
|
if len(rest) > 0 {
|
||||||
node = MakeNodeFromExprs(rest)
|
// n won't be nil here but we should check anyway
|
||||||
|
n := MakeNodeFromExprs(rest)
|
||||||
|
if n == nil {
|
||||||
|
panic("'MakeNodeFromExprs' has returned nil for none empty array of exprs")
|
||||||
|
}
|
||||||
|
node = *n
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeList(node, rest)
|
return MakeList(node, rest)
|
||||||
|
@ -105,7 +110,14 @@ func (l *List) ToSlice() []IExpr {
|
||||||
|
|
||||||
func (l *List) Cons(e IExpr) IExpr {
|
func (l *List) Cons(e IExpr) IExpr {
|
||||||
elements := append([]IExpr{e}, l.ToSlice()...)
|
elements := append([]IExpr{e}, l.ToSlice()...)
|
||||||
return MakeList(MakeNodeFromExprs(elements), elements)
|
node := MakeNodeFromExprs(elements)
|
||||||
|
|
||||||
|
// Since 'elements' is not empty node won't be nil but we should
|
||||||
|
// check anyway
|
||||||
|
if node == nil {
|
||||||
|
node = &l.Node
|
||||||
|
}
|
||||||
|
return MakeList(*node, elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// END: IColl ---
|
// END: IColl ---
|
||||||
|
|
|
@ -199,6 +199,7 @@ func RequireNamespace(rt *Runtime, namespace IExpr) (IExpr, IError) {
|
||||||
|
|
||||||
ns = first.(*Symbol)
|
ns = first.(*Symbol)
|
||||||
alias = second.(*Symbol).GetName()
|
alias = second.(*Symbol).GetName()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, MakeError(rt, ns, "Don't know how to load the given namespace")
|
return nil, MakeError(rt, ns, "Don't know how to load the given namespace")
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (sp *StringParser) Buffer() *[]string {
|
||||||
// points at the current position of the buffer.
|
// points at the current position of the buffer.
|
||||||
func makeErrorAtPoint(p IParsable, msg string, a ...interface{}) IError {
|
func makeErrorAtPoint(p IParsable, msg string, a ...interface{}) IError {
|
||||||
n := MakeSinglePointNode(p.GetSource(), p.GetLocation())
|
n := MakeSinglePointNode(p.GetSource(), p.GetLocation())
|
||||||
return MakeParsetimeErrorf(n, msg, a...)
|
return MakeSyntaxErrorf(n, msg, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeErrorFromError is a function which wraps a Golang error in an IError
|
// makeErrorFromError is a function which wraps a Golang error in an IError
|
||||||
|
@ -407,9 +407,14 @@ func readList(parser IParsable) (IExpr, IError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
node := MakeNodeFromExprs(list)
|
node := MakeNodeFromExprs(list)
|
||||||
|
if node == nil {
|
||||||
|
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
|
||||||
|
node = &n
|
||||||
|
}
|
||||||
|
|
||||||
node.location.DecStart(1)
|
node.location.DecStart(1)
|
||||||
node.location.IncEnd(1)
|
node.location.IncEnd(1)
|
||||||
return MakeList(node, list), nil
|
return MakeList(*node, list), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readComment(parser IParsable) (IExpr, IError) {
|
func readComment(parser IParsable) (IExpr, IError) {
|
||||||
|
@ -443,9 +448,14 @@ func readQuotedExpr(parser IParsable) (IExpr, IError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
listNode := MakeNodeFromExprs(listElems)
|
listNode := MakeNodeFromExprs(listElems)
|
||||||
|
if listNode == nil {
|
||||||
|
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
|
||||||
|
listNode = &n
|
||||||
|
}
|
||||||
|
|
||||||
listNode.location.DecStart(1)
|
listNode.location.DecStart(1)
|
||||||
listNode.location.IncStart(1)
|
listNode.location.IncStart(1)
|
||||||
return MakeList(listNode, listElems), nil
|
return MakeList(*listNode, listElems), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readUnquotedExpr reads different unquoting expressions from their short representaions.
|
// readUnquotedExpr reads different unquoting expressions from their short representaions.
|
||||||
|
@ -489,10 +499,19 @@ func readUnquotedExpr(parser IParsable) (IExpr, IError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
listElems := []IExpr{sym, expr}
|
listElems := []IExpr{sym, expr}
|
||||||
|
|
||||||
listNode := MakeNodeFromExprs(listElems)
|
listNode := MakeNodeFromExprs(listElems)
|
||||||
|
|
||||||
|
// listNode won't be nil in this case but it doesn't
|
||||||
|
// mean we shouldn't check
|
||||||
|
if listNode == nil {
|
||||||
|
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
|
||||||
|
listNode = &n
|
||||||
|
}
|
||||||
|
|
||||||
listNode.location.DecStart(1)
|
listNode.location.DecStart(1)
|
||||||
listNode.location.IncStart(1)
|
listNode.location.IncStart(1)
|
||||||
return MakeList(listNode, listElems), nil
|
return MakeList(*listNode, listElems), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readQuasiquotedExpr reads the backquote and replace it with a call
|
// readQuasiquotedExpr reads the backquote and replace it with a call
|
||||||
|
@ -512,10 +531,17 @@ func readQuasiquotedExpr(parser IParsable) (IExpr, IError) {
|
||||||
|
|
||||||
listElems := []IExpr{sym, expr}
|
listElems := []IExpr{sym, expr}
|
||||||
listNode := MakeNodeFromExprs(listElems)
|
listNode := MakeNodeFromExprs(listElems)
|
||||||
|
// listNode won't be nil in this case but it doesn't
|
||||||
|
// mean we shouldn't check
|
||||||
|
if listNode == nil {
|
||||||
|
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
|
||||||
|
listNode = &n
|
||||||
|
}
|
||||||
|
|
||||||
listNode.location.DecStart(1)
|
listNode.location.DecStart(1)
|
||||||
listNode.location.IncStart(1)
|
listNode.location.IncStart(1)
|
||||||
|
|
||||||
return MakeList(listNode, listElems), nil
|
return MakeList(*listNode, listElems), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readExpr reads one expression from the input. This function is the most
|
// readExpr reads one expression from the input. This function is the most
|
||||||
|
|
|
@ -65,9 +65,11 @@ func Println(rt *Runtime, ast ...IRepresentable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrintError(rt *Runtime, err IError) {
|
func PrintError(rt *Runtime, err IError) {
|
||||||
trace := err.GetStackTrace()
|
|
||||||
|
|
||||||
|
trace := err.GetStackTrace()
|
||||||
|
fmt.Println(err)
|
||||||
for i, t := range *trace {
|
for i, t := range *trace {
|
||||||
|
fmt.Println(*t)
|
||||||
caller := t.Caller
|
caller := t.Caller
|
||||||
callerLoc := caller.GetLocation()
|
callerLoc := caller.GetLocation()
|
||||||
callerSource := callerLoc.GetSource()
|
callerSource := callerLoc.GetSource()
|
||||||
|
@ -82,7 +84,11 @@ func PrintError(rt *Runtime, err IError) {
|
||||||
|
|
||||||
var lines string
|
var lines string
|
||||||
for i := startline; i <= endline; i++ {
|
for i := startline; i <= endline; i++ {
|
||||||
lines += fmt.Sprintf("%d:\t%s\n", i, t.Fn.GetLocation().GetSource().GetLine(i))
|
fmt.Println(">>>>>>>>>> ", err)
|
||||||
|
fLoc := t.Fn.GetLocation()
|
||||||
|
fmt.Println(">>>>>>>>>> ", fLoc, fLoc.GetSource())
|
||||||
|
|
||||||
|
lines += fmt.Sprintf("%d:\t%s\n", i, fLoc.GetSource().GetLine(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
color.Yellow.Printf(
|
color.Yellow.Printf(
|
||||||
|
|
|
@ -103,8 +103,12 @@ func qqProcess(rt *Runtime, e IExpr) (IExpr, IError) {
|
||||||
e,
|
e,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n := MakeNodeFromExprs(elems)
|
||||||
|
if n == nil {
|
||||||
|
n = &sym.Node
|
||||||
|
}
|
||||||
return MakeList(
|
return MakeList(
|
||||||
MakeNodeFromExprs(elems),
|
*n,
|
||||||
elems,
|
elems,
|
||||||
), nil
|
), nil
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"serene-lang.org/bootstrap/pkg/ast"
|
"serene-lang.org/bootstrap/pkg/ast"
|
||||||
|
@ -86,7 +85,7 @@ func MakeSymbol(n Node, s string) (*Symbol, IError) {
|
||||||
name = parts[1]
|
name = parts[1]
|
||||||
nsPart = parts[0]
|
nsPart = parts[0]
|
||||||
default:
|
default:
|
||||||
return nil, MakePlainError(fmt.Sprintf("can't create a symbol from '%s'. More that on '/' is illegal.", s))
|
return nil, MakeSyntaxErrorf(n, "can't create a symbol from '%s'. More that on '/' is illegal.", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Symbol{
|
return &Symbol{
|
||||||
|
|
|
@ -122,6 +122,12 @@ func toRepresentables(ast IColl) []IRepresentable {
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: I don't like the current interface and signatures of these
|
||||||
|
// 'Make*Node*' functions. Refactor them to have the same interface
|
||||||
|
// For instance if we need to return a pointer to a Node all of them
|
||||||
|
// has to return a pointer not just one of them. The return type
|
||||||
|
// should be predictable
|
||||||
|
|
||||||
// MakeNodeFromLocation creates a new Node for the given Location `loc`
|
// MakeNodeFromLocation creates a new Node for the given Location `loc`
|
||||||
func MakeNodeFromLocation(loc *ast.Location) Node {
|
func MakeNodeFromLocation(loc *ast.Location) Node {
|
||||||
return Node{
|
return Node{
|
||||||
|
@ -139,17 +145,16 @@ func MakeNodeFromExpr(e IExpr) Node {
|
||||||
// MakeNodeFromExprs creates a new Node from the given slice of `IExpr`s.
|
// MakeNodeFromExprs creates a new Node from the given slice of `IExpr`s.
|
||||||
// We use the Node to pass it to other IExpr constructors to
|
// We use the Node to pass it to other IExpr constructors to
|
||||||
// keep the reference to the original form in the input string
|
// keep the reference to the original form in the input string
|
||||||
func MakeNodeFromExprs(es []IExpr) Node {
|
func MakeNodeFromExprs(es []IExpr) *Node {
|
||||||
if len(es) == 0 {
|
if len(es) == 0 {
|
||||||
// TODO: This is temporary, fix it.
|
return nil
|
||||||
panic("can't create a node from empty elements.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
firstLoc := es[0].GetLocation()
|
firstLoc := es[0].GetLocation()
|
||||||
endLoc := es[len(es)-1].GetLocation()
|
endLoc := es[len(es)-1].GetLocation()
|
||||||
loc := ast.MakeLocation(firstLoc.GetSource(), firstLoc.GetStart(), endLoc.GetEnd())
|
loc := ast.MakeLocation(firstLoc.GetSource(), firstLoc.GetStart(), endLoc.GetEnd())
|
||||||
|
n := MakeNodeFromLocation(loc)
|
||||||
return MakeNodeFromLocation(loc)
|
return &n
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeNode creates a new Node in the the given `input` that points to a
|
// MakeNode creates a new Node in the the given `input` that points to a
|
||||||
|
|
Loading…
Reference in New Issue