Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: add code export and import #85

Open
apoorvcodes opened this issue Jan 4, 2023 · 2 comments
Open

Feat: add code export and import #85

apoorvcodes opened this issue Jan 4, 2023 · 2 comments

Comments

@apoorvcodes
Copy link

Add some way to export or import codebases from other files for example

Export

export {
  foo
}

Import

import ( "src/export.monkey")
@skx
Copy link
Owner

skx commented Jan 7, 2023

That's an interesting idea, thanks for the suggestion.

I suspect I would not work on such a thing, but if you were willing to contribute I'd accept.

There are probably questions to be asked first though, like how this would affect scoping. The simple approach, like C using "include" would be easy to add, and could be done at the lexer/parser level:

#include "blah.monkey"

That works. But if you had an import like this:

import "time"

Where "time.monkey" had:

function today() { return "Monday"; }

Would that be called as today(), or time.today() ? Similarly how would you handle things that were public vs. private?

And finally would you need to support some kind of search-path, as used in perl/python?

@csd129
Copy link

csd129 commented Nov 27, 2023

The code below allows for monkey files to be imported, if you want play with or certainly improve.
So if a file, say foo.monkey contains

function today() { return "Monday"; }

It will be imported with
include("foo")

with the imported file being within the env var INCLUDEPATH or in the directory /usr/local/include/monkey or current directory.

The function would be called with today()

package evaluator

import (
	"os"
	"fmt"
	"strings"
	"monkey/object"
	"monkey/lexer"
	"monkey/parser"
)

func Include(env *object.Environment, args ...object.Object) object.Object {
	import_file:=args[0].Inspect()
	includes:=""
	if len(import_file) == 0 {
		return newError("ArgError: include() expects a file identifier, none given")
	}
	imp_filename:=fmt.Sprintf("%s.monkey", import_file)
	userincludes:=os.Getenv("INCLUDEPATH")
	if len(userincludes) == 0 {
		includes="/usr/local/include/monkey:."
	} else {
		includes=fmt.Sprintf("%s:%s", userincludes, "/usr/local/include/monkey:." )
	}
	incpaths:=strings.Split(includes, ":")
	for _, ipath := range incpaths {
		import_file=fmt.Sprintf("%s/%s", ipath, imp_filename)
		data, err := os.ReadFile(import_file)
		if err == nil {
			l := lexer.New(string(data))
			p := parser.New(l)
			program := p.ParseProgram()
			if len(p.Errors()) == 0 {
				Eval(program, env)
				return nil
			}
			fmt.Printf("Error parsing eval-string: %s", string(data))
			os.Exit(1)
		}
	}
	return newError("Unable to open file %s", imp_filename)
}

func init() {
	RegisterBuiltin("include",
		func(env *object.Environment, args ...object.Object) object.Object {
			return (Include(env, args...))
		})
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants