Skip to content

Commit

Permalink
Adding capability to register modules via type system. This way 'std'…
Browse files Browse the repository at this point in the history
… module is not implicitely available, it now should be explicitely imported for usage which is a good thing (tm)
  • Loading branch information
pachanga committed Jul 22, 2022
1 parent 07b1656 commit d20b4f5
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 71 deletions.
1 change: 1 addition & 0 deletions example/hello/hello.bhl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import "std"

func main([]string argv) {
paral {
Expand Down
39 changes: 0 additions & 39 deletions src/compile/compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,6 @@

namespace bhl {

public class ModulePath
{
public string name;
public string file_path;

public ModulePath(string name, string file_path)
{
this.name = name;
this.file_path = file_path;
}
}

public class Module
{
public string name {
get {
return path.name;
}
}
public string file_path {
get {
return path.file_path;
}
}
public ModulePath path;
public HashSet<string> imports = new HashSet<string>();
public Namespace ns;

public Module(Types ts, ModulePath path)
{
this.path = path;
ns = new Namespace(ts.gindex, "", name);
}

public Module(Types ts, string name, string file_path)
: this(ts, new ModulePath(name, file_path))
{}
}

public class ModuleCompiler : AST_Visitor
{
AST_Tree ast;
Expand Down
44 changes: 29 additions & 15 deletions src/compile/parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,24 +231,38 @@ public Module GetModule(string norm_path)
}

//NOTE: returns normalized imported module path
//TODO: the code below is kinda 'fishy' but works
public string RequestImport(Module origin, Types ts, string path)
{
string full_path;
string norm_path;
ResolvePath(origin.file_path, path, out full_path, out norm_path);

if(!imports.ContainsKey(norm_path))
//1. check pre-registered module
Module m = ts.FindRegisteredModule(path);
if(m != null)
{
//NOTE: If a module wasn't registered (by some processor) we create a module and processor for it.
// Otherwise we re-use the already registered module. This way we share symbols across
// all the parsed/imported modules and don't do any 'double work'
if(!modules.ContainsKey(norm_path))
{
var m = new Module(ts, norm_path, full_path);
norm_path = m.name;
if(!imports.ContainsKey(norm_path))
RegisterModule(m);
}
//2. try filesystem
else
{
string file_path;
ResolvePath(origin.file_path, path, out file_path, out norm_path);

var proc = MakeProcessor(full_path, m, ts);
imports.Add(norm_path, proc);
if(!imports.ContainsKey(norm_path))
{
//NOTE: If a module wasn't registered (by some processor) we create a module and processor for it.
// Otherwise we re-use the already registered module. This way we share symbols across
// all the parsed/imported modules and don't do any 'double work'
if(!modules.ContainsKey(norm_path))
{
m = new Module(ts, norm_path, file_path);
RegisterModule(m);

var proc = MakeProcessor(file_path, m, ts);
imports.Add(norm_path, proc);
}
}
}

Expand Down Expand Up @@ -284,16 +298,16 @@ ANTLR_Processor MakeProcessor(string full_path, Module m, Types ts)
return proc;
}

void ResolvePath(string self_path, string path, out string full_path, out string norm_path)
void ResolvePath(string self_path, string path, out string file_path, out string norm_path)
{
full_path = "";
file_path = "";
norm_path = "";

if(path.Length == 0)
throw new Exception("Bad path");

full_path = Util.ResolveImportPath(include_path, self_path, path);
norm_path = FilePath2ModuleName(full_path);
file_path = Util.ResolveImportPath(include_path, self_path, path);
norm_path = FilePath2ModuleName(file_path);
}

public string FilePath2ModuleName(string full_path)
Expand Down
7 changes: 5 additions & 2 deletions src/std/std.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ namespace bhl {

public static class std
{
static public void Init(Types ts)
static public Module MakeModule(Types ts)
{
var io = ts.ns.Nest("std").Nest("io");
var m = new Module(ts, "std", null);

var io = m.ns.Nest("std").Nest("io");

{
var fn = new FuncSymbolNative("Write", ts.T("void"),
Expand All @@ -33,6 +35,7 @@ static public void Init(Types ts)
);
io.Define(fn);
}
return m;
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/vm/type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,8 @@ public class Types : INamedResolver
//NOTE: used for global symbol indices (e.g native funcs)
public Named2Index gindex = new Named2Index();

Dictionary<string, Module> modules = new Dictionary<string, Module>();

static Types()
{
{
Expand Down Expand Up @@ -491,7 +493,19 @@ public Types()

InitBuiltins();

std.Init(this);
RegisterModule(std.MakeModule(this));
}

public void RegisterModule(Module m)
{
modules.Add(m.name, m);
}

public Module FindRegisteredModule(string name)
{
Module m;
modules.TryGetValue(name, out m);
return m;
}

Types(Named2Index native_indices, Namespace ns)
Expand Down
39 changes: 39 additions & 0 deletions src/vm/vm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,45 @@ public bool Equals(Const o)
}
}

public class ModulePath
{
public string name;
public string file_path;

public ModulePath(string name, string file_path)
{
this.name = name;
this.file_path = file_path;
}
}

public class Module
{
public string name {
get {
return path.name;
}
}
public string file_path {
get {
return path.file_path;
}
}
public ModulePath path;
public HashSet<string> imports = new HashSet<string>();
public Namespace ns;

public Module(Types ts, ModulePath path)
{
this.path = path;
ns = new Namespace(ts.gindex, "", name);
}

public Module(Types ts, string name, string file_path)
: this(ts, new ModulePath(name, file_path))
{}
}

public class VM : INamedResolver
{
public const int MAX_IP = int.MaxValue;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_maps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void TestSimpleDeclare()
new ModuleCompiler()
.UseInit()
.EmitThen(Opcodes.New, new int[] { ConstIdx(c, c.ns.TMap("string", "int")) })
.EmitThen(Opcodes.SetVar, new int[] { 0+1/*std namespace*/ })
.EmitThen(Opcodes.SetVar, new int[] { 0 })
;

AssertEqual(c, expected);
Expand Down
26 changes: 13 additions & 13 deletions tests/test_vm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18253,10 +18253,10 @@ func float test()
var expected =
new ModuleCompiler()
.UseInit()
.EmitThen(Opcodes.DeclVar, new int[] { 1+1/*std namespace*/, ConstIdx(c, ts.T("float")) })
.EmitThen(Opcodes.DeclVar, new int[] { 1, ConstIdx(c, ts.T("float")) })
.UseCode()
.EmitThen(Opcodes.InitFrame, new int[] { 1 /*args info*/})
.EmitThen(Opcodes.GetGVar, new int[] { 2 })
.EmitThen(Opcodes.GetGVar, new int[] { 1 })
.EmitThen(Opcodes.ReturnVal, new int[] { 1 })
.EmitThen(Opcodes.Return)
;
Expand Down Expand Up @@ -18287,12 +18287,12 @@ func float test()
new ModuleCompiler()
.UseInit()
.EmitThen(Opcodes.Constant, new int[] { ConstIdx(c, 10) })
.EmitThen(Opcodes.SetVar, new int[] { 1+1/*std namespace*/ })
.EmitThen(Opcodes.SetVar, new int[] { 1 })
.UseCode()
.EmitThen(Opcodes.InitFrame, new int[] { 1 /*args info*/})
.EmitThen(Opcodes.Constant, new int[] { ConstIdx(c, 20) })
.EmitThen(Opcodes.SetGVar, new int[] { 2 })
.EmitThen(Opcodes.GetGVar, new int[] { 2 })
.EmitThen(Opcodes.SetGVar, new int[] { 1 })
.EmitThen(Opcodes.GetGVar, new int[] { 1 })
.EmitThen(Opcodes.ReturnVal, new int[] { 1 })
.EmitThen(Opcodes.Return)
;
Expand Down Expand Up @@ -18322,10 +18322,10 @@ func float test()
new ModuleCompiler()
.UseInit()
.EmitThen(Opcodes.Constant, new int[] { ConstIdx(c, 10) })
.EmitThen(Opcodes.SetVar, new int[] { 1+1/*std namespace*/ })
.EmitThen(Opcodes.SetVar, new int[] { 1 })
.UseCode()
.EmitThen(Opcodes.InitFrame, new int[] { 1 /*args info*/})
.EmitThen(Opcodes.GetGVar, new int[] { 2 })
.EmitThen(Opcodes.GetGVar, new int[] { 1 })
.EmitThen(Opcodes.ReturnVal, new int[] { 1 })
.EmitThen(Opcodes.Return)
;
Expand Down Expand Up @@ -19066,26 +19066,26 @@ public void TestSerializeModuleSymbols()
Marshall.Stream2Obj(s, ns, factory);

AssertEqual(8 + ts.ns.members.Count, ns.GetSymbolsEnumerator().Count);
AssertEqual(8 + 1/*std namespace*/ + 1/*extra std bug*/, ns.members.Count);
AssertEqual(8, ns.members.Count);

var foo = (VariableSymbol)ns.Resolve("foo");
AssertEqual(foo.name, "foo");
AssertEqual(foo.type.Get(), Types.Int);
AssertEqual(foo.scope, ns);
AssertEqual(foo.scope_idx, 0+1/*std namespace*/);
AssertEqual(foo.scope_idx, 0);

var bar = (VariableSymbol)ns.Resolve("bar");
AssertEqual(bar.name, "bar");
AssertEqual(bar.type.Get(), Types.String);
AssertEqual(bar.scope, ns);
AssertEqual(bar.scope_idx, 1+1/*std namespace*/);
AssertEqual(bar.scope_idx, 1);

var wow = (VariableSymbol)ns.Resolve("wow");
AssertEqual(wow.name, "wow");
AssertEqual(wow.type.Get().GetName(), ns.TArr(Types.Bool).Get().GetName());
AssertEqual(((GenericArrayTypeSymbol)wow.type.Get()).item_type.Get(), Types.Bool);
AssertEqual(wow.scope, ns);
AssertEqual(wow.scope_idx, 2+1/*std namespace*/);
AssertEqual(wow.scope_idx, 2);

var Test = (FuncSymbolScript)ns.Resolve("Test");
AssertEqual(Test.name, "Test");
Expand All @@ -19094,7 +19094,7 @@ public void TestSerializeModuleSymbols()
AssertEqual(1, Test.default_args_num);
AssertEqual(0, Test.local_vars_num);
AssertEqual(155, Test.ip_addr);
AssertEqual(3+1/*std namespace*/, Test.scope_idx);
AssertEqual(3, Test.scope_idx);

var Make = (FuncSymbolScript)ns.Resolve("Make");
AssertEqual(Make.name, "Make");
Expand All @@ -19105,7 +19105,7 @@ public void TestSerializeModuleSymbols()
AssertEqual(3, Make.default_args_num);
AssertEqual(0, Make.local_vars_num);
AssertEqual(15, Make.ip_addr);
AssertEqual(4+1/*std namespace*/, Make.scope_idx);
AssertEqual(4, Make.scope_idx);

var Foo = (ClassSymbolScript)ns.Resolve("Foo");
AssertEqual(Foo.scope, ns);
Expand Down

0 comments on commit d20b4f5

Please sign in to comment.