module support
This commit is contained in:
@@ -4,7 +4,11 @@ import (
|
||||
"fmt"
|
||||
"monkey/ast"
|
||||
"monkey/builtins"
|
||||
"monkey/lexer"
|
||||
"monkey/object"
|
||||
"monkey/parser"
|
||||
"monkey/utils"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -40,6 +44,9 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
case *ast.WhileExpression:
|
||||
return evalWhileExpression(node, env)
|
||||
|
||||
case *ast.ImportExpression:
|
||||
return evalImportExpression(node, env)
|
||||
|
||||
case *ast.ReturnStatement:
|
||||
val := Eval(node.ReturnValue, env)
|
||||
if isError(val) {
|
||||
@@ -190,6 +197,22 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
func evalImportExpression(ie *ast.ImportExpression, env *object.Environment) object.Object {
|
||||
name := Eval(ie.Name, env)
|
||||
if isError(name) {
|
||||
return name
|
||||
}
|
||||
|
||||
if s, ok := name.(*object.String); ok {
|
||||
attrs := EvalModule(s.Value)
|
||||
if isError(attrs) {
|
||||
return attrs
|
||||
}
|
||||
return &object.Module{Name: s.Value, Attrs: attrs}
|
||||
}
|
||||
return newError("ImportError: invalid import path '%s'", name)
|
||||
}
|
||||
|
||||
func evalWhileExpression(we *ast.WhileExpression, env *object.Environment) object.Object {
|
||||
var result object.Object
|
||||
|
||||
@@ -208,9 +231,9 @@ func evalWhileExpression(we *ast.WhileExpression, env *object.Environment) objec
|
||||
|
||||
if result != nil {
|
||||
return result
|
||||
} else {
|
||||
return NULL
|
||||
}
|
||||
|
||||
return NULL
|
||||
}
|
||||
|
||||
func evalProgram(program *ast.Program, env *object.Environment) object.Object {
|
||||
@@ -485,6 +508,29 @@ func newError(format string, a ...interface{}) *object.Error {
|
||||
return &object.Error{Message: fmt.Sprintf(format, a...)}
|
||||
}
|
||||
|
||||
// EvalModule evaluates the named module and returns a *object.Module objec
|
||||
func EvalModule(name string) object.Object {
|
||||
filename := utils.FindModule(name)
|
||||
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return newError("IOError: error reading module '%s': %s", name, err)
|
||||
}
|
||||
|
||||
l := lexer.New(string(b))
|
||||
p := parser.New(l)
|
||||
|
||||
module := p.ParseProgram()
|
||||
if len(p.Errors()) != 0 {
|
||||
return newError("ParseError: %s", p.Errors())
|
||||
}
|
||||
|
||||
env := object.NewEnvironment()
|
||||
Eval(module, env)
|
||||
|
||||
return env.ExportedHash()
|
||||
}
|
||||
|
||||
func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object {
|
||||
if val, ok := env.Get(node.Value); ok {
|
||||
return val
|
||||
@@ -557,11 +603,18 @@ func evalIndexExpression(left, index object.Object) object.Object {
|
||||
return evalArrayIndexExpression(left, index)
|
||||
case left.Type() == object.HASH_OBJ:
|
||||
return evalHashIndexExpression(left, index)
|
||||
case left.Type() == object.MODULE_OBJ:
|
||||
return EvalModuleIndexExpression(left, index)
|
||||
default:
|
||||
return newError("index operator not supported: %s", left.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func EvalModuleIndexExpression(module, index object.Object) object.Object {
|
||||
moduleObject := module.(*object.Module)
|
||||
return evalHashIndexExpression(moduleObject.Attrs, index)
|
||||
}
|
||||
|
||||
func evalStringIndexExpression(str, index object.Object) object.Object {
|
||||
stringObject := str.(*object.String)
|
||||
idx := index.(*object.Integer).Value
|
||||
|
||||
Reference in New Issue
Block a user