示例#1
0
        public static MondValue Run(string source)
        {
            var state   = new MondState();
            var program = MondProgram.Compile(source);

            return(state.Load(program));
        }
示例#2
0
        static void ScriptMain(TextReader input, string fileName)
        {
            var state = new MondState();

            Functions.Register(state);

            string source;

            try
            {
                source = input.ReadToEnd();
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to read '{0}':", fileName);
                Console.WriteLine(e);
                return;
            }

            try
            {
                var program = MondProgram.Compile(Functions.Definitions + source, Path.GetFileName(fileName));
                var result  = state.Load(program);

                if (result != MondValue.Undefined)
                {
                    result.Serialize(Console.Out);
                    Console.WriteLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
示例#3
0
        public static MondState Load(params string[] sources)
        {
            var state = new MondState();

            foreach (var source in sources)
            {
                var program = MondProgram.Compile(source);
                state.Load(program);
            }

            return(state);
        }
示例#4
0
        public void NativeFunction()
        {
            var state = new MondState();

            state["function"] = new MondFunction((_, args) => args[0]);

            var program = MondProgram.Compile(@"
                return global.function('arg');
            ");

            var result = state.Load(program);

            Assert.True(result == "arg");
        }
示例#5
0
        public void NativeInstanceFunction()
        {
            var state = new MondState();

            state["value"]    = 123;
            state["function"] = new MondInstanceFunction((_, instance, arguments) => instance[arguments[0]]);

            var program = MondProgram.Compile(@"
                return global.function('value');
            ");

            var result = state.Load(program);

            Assert.True(result == 123);
        }
示例#6
0
        private static MondValue Require(MondState state, params MondValue[] arguments)
        {
            if (arguments.Length < 1)
            {
                throw new MondRuntimeException("require: must be called with 1 argument");
            }

            if (arguments[0].Type != MondValueType.String)
            {
                throw new MondRuntimeException("require: argument 1 must be of type String");
            }

            var fileName = (string)arguments[0];
            var program  = MondProgram.Compile(Definitions + File.ReadAllText(fileName), fileName);

            return(state.Load(program));
        }
示例#7
0
        public MondValue Require(MondState state, string fileName)
        {
            if (_require.Loader == null)
            {
                throw new MondRuntimeException("require: module loader is not set");
            }

            const string cacheObjectName = "__modules";

            MondValue cacheObject;

            // make sure we have somewhere to cache modules
            if (state[cacheObjectName].Type != MondValueType.Object)
            {
                cacheObject            = new MondValue(state);
                cacheObject.Prototype  = MondValue.Null;
                state[cacheObjectName] = cacheObject;
            }
            else
            {
                cacheObject = state[cacheObjectName];
            }

            // return cached module if it exists
            var cachedExports = cacheObject[fileName];

            if (cachedExports.Type == MondValueType.Object)
            {
                return(cachedExports);
            }

            // create a new object to store the exports
            var exports = new MondValue(state);

            exports.Prototype = MondValue.Null;

            // instantly cache it so we can have circular dependencies
            cacheObject[fileName] = exports;

            try
            {
                IEnumerable <string> searchDirectories =
                    _require.SearchDirectories ?? Array.Empty <string>();

                if (_require.SearchBesideScript)
                {
                    var currentDir = Path.GetDirectoryName(state.CurrentScript);
                    searchDirectories = Enumerable.Repeat(currentDir, 1)
                                        .Concat(searchDirectories);
                }

                var moduleSource = _require.Loader(fileName, searchDirectories);

                // wrap the module script in a function so we can pass out exports object to it
                var source = _require.Definitions + "return fun (exports) {\n" + moduleSource + " return exports; };";

                var options = new MondCompilerOptions
                {
                    FirstLineNumber = -1
                };

                var requireOptions = _require.Options;
                if (requireOptions != null)
                {
                    options.DebugInfo = requireOptions.DebugInfo;
                    options.MakeRootDeclarationsGlobal = requireOptions.MakeRootDeclarationsGlobal;
                    options.UseImplicitGlobals         = requireOptions.UseImplicitGlobals;
                }

                var program     = MondProgram.Compile(source, fileName, options);
                var initializer = state.Load(program);

                var result = state.Call(initializer, exports);

                if (result.Type != MondValueType.Object)
                {
                    throw new MondRuntimeException("require: module must return an object (`{0}`)", fileName);
                }

                if (!ReferenceEquals(exports, result))
                {
                    // module returned a different object, merge with ours
                    foreach (var kv in result.Object)
                    {
                        var key   = kv.Key;
                        var value = kv.Value;

                        exports[key] = value;
                    }

                    exports.Prototype = result.Prototype;

                    if (result.IsLocked)
                    {
                        exports.Lock();
                    }
                }
            }
            catch
            {
                // if something goes wrong, remove the entry from the cache
                cacheObject[fileName] = MondValue.Undefined;
                throw;
            }

            return(exports);
        }