// Creates a new function object with the given code and constants. The new // function will take over ownership of [bytecode] and [sourceLines]. It will // copy [constants] into its own array. public ObjFn(ObjModule module, Obj[] constants, int numUpvalues, int arity, byte[] bytecode) { Bytecode = bytecode; Constants = constants; Module = module; NumUpvalues = numUpvalues; Arity = arity; ClassObj = SophieVM.FnClass; }
public SophieVM() { MethodNames = new List<string>(); ObjString name = Obj.MakeString("core"); // Implicitly create a "core" module for the built in libraries. ObjModule coreModule = new ObjModule(name); _modules = new ObjMap(); _modules.Set(Obj.Null, coreModule); CoreLibrary core = new CoreLibrary(this); core.InitializeCore(); // Load in System functions Library.System.LoadSystemLibrary(this); }
public static ObjFn Compile(SophieVM vm, ObjModule module, string sourcePath, string source, bool printErrors) { Parser parser = new Parser { Vm = vm, Module = module, SourcePath = sourcePath, Source = source, TokenStart = 0, CurrentChar = 0, CurrentLine = 1, Current = { Type = TokenType.Error, Start = 0, Length = 0, Line = 0 }, PrintErrors = printErrors, HasError = false, Raw = "" }; Compiler compiler = new Compiler(parser, null, true); // Read the first token. compiler.NextToken(); compiler.IgnoreNewlines(); while (!compiler.Match(TokenType.Eof)) { compiler.Definition(); // If there is no newline, it must be the end of the block on the same line. if (!compiler.MatchLine()) { compiler.Consume(TokenType.Eof, "Expect end of file."); break; } } compiler.Emit(Instruction.Null); compiler.Emit(Instruction.Return); // See if there are any implicitly declared module-level variables that never // got an explicit definition. // TODO: It would be nice if the error was on the line where it was used. for (int i = 0; i < parser.Module.Variables.Count; i++) { ModuleVariable t = parser.Module.Variables[i]; if (t.Container == Obj.Undefined) { compiler.Error(string.Format("Variable '{0}' is used but not defined.", t.Name)); } } return compiler.EndCompiler(); }
private ObjFiber LoadModule(Obj name, string source) { ObjModule module = GetModule(name); // See if the module has already been loaded. if (module == null) { module = new ObjModule(name as ObjString); // Store it in the VM's module registry so we don't load the same module // multiple times. _modules.Set(name, module); // Implicitly import the core module. ObjModule coreModule = GetCoreModule(); foreach (ModuleVariable t in coreModule.Variables) { DefineVariable(module, t.Name, t.Container); } } ObjFn fn = Compiler.Compile(this, module, name.ToString(), source, true); if (fn == null) { // TODO: Should we still store the module even if it didn't compile? return null; } ObjFiber moduleFiber = new ObjFiber(fn); // Return the fiber that executes the module. return moduleFiber; }
internal int DefineVariable(ObjModule module, string name, Obj c) { if (module == null) module = GetCoreModule(); if (module.Variables.Count == ObjModule.MaxModuleVars) return -2; // See if the variable is already explicitly or implicitly declared. int symbol = module.Variables.FindIndex(m => m.Name == name); if (symbol == -1) { // Brand new variable. module.Variables.Add(new ModuleVariable { Name = name, Container = c }); symbol = module.Variables.Count - 1; } else if (module.Variables[symbol].Container == Obj.Undefined) { // Explicitly declaring an implicitly declared one. Mark it as defined. module.Variables[symbol].Container = c; } else { // Already explicitly declared. symbol = -1; } return symbol; }
internal int DeclareVariable(ObjModule module, string name) { if (module == null) module = GetCoreModule(); if (module.Variables.Count == ObjModule.MaxModuleVars) return -2; module.Variables.Add(new ModuleVariable { Name = name, Container = Obj.Undefined }); return module.Variables.Count - 1; }