diff --git a/runtime/src/main/java/dev/ionfusion/fusion/Binding.java b/runtime/src/main/java/dev/ionfusion/fusion/Binding.java index 59c2152f..02b42ac7 100644 --- a/runtime/src/main/java/dev/ionfusion/fusion/Binding.java +++ b/runtime/src/main/java/dev/ionfusion/fusion/Binding.java @@ -102,7 +102,7 @@ boolean sameTarget(Binding other) * exported identifier. May be null if the name isn't explicitly given * in the form, as in {@code (provide (all_defined_out))}. */ - ProvidedBinding provideAs(BaseSymbol name, ResourcePosition idLocation) + ProvidedBinding provideAs(BaseSymbol name, ResourcePosition idLocation) { throw new IllegalStateException("This kind of binding can't be exported"); } diff --git a/runtime/src/main/java/dev/ionfusion/fusion/ModuleNamespace.java b/runtime/src/main/java/dev/ionfusion/fusion/ModuleNamespace.java index 3d585fc0..11bfee5c 100644 --- a/runtime/src/main/java/dev/ionfusion/fusion/ModuleNamespace.java +++ b/runtime/src/main/java/dev/ionfusion/fusion/ModuleNamespace.java @@ -28,16 +28,19 @@ final class ModuleNamespace extends Namespace { - static abstract class ProvidedBinding + static abstract class ProvidedBinding extends Binding { private final BaseSymbol myName; private final ResourcePosition myLoc; + private final InsideBinding myInside; - ProvidedBinding(BaseSymbol name, ResourcePosition sourceLocation) + ProvidedBinding(BaseSymbol name, ResourcePosition sourceLocation, + InsideBinding inside) { myName = name; myLoc = sourceLocation; + myInside = inside; } @Override @@ -50,21 +53,23 @@ BindingSite bindingSite() } @Override - final ProvidedBinding provideAs(BaseSymbol name, - ResourcePosition sourceLocation) + final ProvidedBinding provideAs(BaseSymbol name, + ResourcePosition sourceLocation) { - return new ImportedProvidedBinding(name, sourceLocation, this); + return new ImportedProvidedBinding<>(name, sourceLocation, this); } /** * Gets the binding that's being exported, either a definition or * import. */ - abstract Binding inside(); + InsideBinding inside() + { + return myInside; + } @Override abstract ModuleDefinedBinding target(); - abstract ModuleIdentity getTargetModule(); @Override final Object lookup(Namespace ns) @@ -77,18 +82,15 @@ final Object lookup(Namespace ns) * A provided binding that was defined in the providing module. */ static final class DefinedProvidedBinding - extends ProvidedBinding + extends ProvidedBinding { - private final ModuleDefinedBinding myDefinition; - DefinedProvidedBinding(BaseSymbol name, ResourcePosition sourceLocation, ModuleDefinedBinding binding) { - super(name, sourceLocation); + super(name, sourceLocation, binding); assert binding.target() == binding; - myDefinition = binding; } DefinedProvidedBinding(ModuleDefinedBinding binding) @@ -98,22 +100,10 @@ static final class DefinedProvidedBinding binding); } - @Override - Binding inside() - { - return myDefinition; - } - @Override ModuleDefinedBinding target() { - return myDefinition; - } - - @Override - ModuleIdentity getTargetModule() - { - return myDefinition.myModuleId; + return inside(); } @Override @@ -125,43 +115,27 @@ Object visit(Visitor v) throws FusionException @Override public String toString() { - return "{{{DefinedProvidedBinding " + getName() - + " -> " + myDefinition + "}}}"; + return "{{{DefinedProvidedBinding " + getName() + " -> " + inside() + "}}}"; } } /** * A provided binding that was imported into the providing module. */ - static final class ImportedProvidedBinding - extends ProvidedBinding + static final class ImportedProvidedBinding + extends ProvidedBinding> { - private final ProvidedBinding myImport; - ImportedProvidedBinding(BaseSymbol name, ResourcePosition sourceLocation, - ProvidedBinding imported) - { - super(name, sourceLocation); - myImport = imported; - } - - @Override - Binding inside() + ProvidedBinding imported) { - return myImport; + super(name, sourceLocation, imported); } @Override ModuleDefinedBinding target() { - return myImport.target(); - } - - @Override - ModuleIdentity getTargetModule() - { - return myImport.getTargetModule(); + return inside().target(); } @Override @@ -173,8 +147,7 @@ Object visit(Visitor v) throws FusionException @Override public String toString() { - return "{{{ImportedProvidedBinding " + getName() - + " -> " + myImport + "}}}"; + return "{{{ImportedProvidedBinding " + getName() + " -> " + inside() + "}}}"; } } diff --git a/runtime/src/main/java/dev/ionfusion/fusion/ProvideForm.java b/runtime/src/main/java/dev/ionfusion/fusion/ProvideForm.java index c51fa3f6..08b40bcf 100644 --- a/runtime/src/main/java/dev/ionfusion/fusion/ProvideForm.java +++ b/runtime/src/main/java/dev/ionfusion/fusion/ProvideForm.java @@ -134,7 +134,7 @@ private void expandProvideSexp(Evaluator eval, SyntaxSymbol specId = specForm.firstIdentifier(eval); if (isCoreForm(eval, specForm, ALL_DEFINED_OUT)) { - // Expanded form is a sequence of identifiers. + // Expanded form adds a sequence of defined identifiers check.arityExact(1); @@ -161,6 +161,7 @@ private void expandProvideSexp(Evaluator eval, binding.getName(), specId, null); + // TODO Shouldn't this have syntaxTrackOrigin as well? Binding localBinding = moduleNamespace.resolveDefinition(localized); if (localBinding != null && binding.sameTarget(localBinding)) { @@ -168,8 +169,7 @@ private void expandProvideSexp(Evaluator eval, expanded.add(localized); } - // TODO handle rename-transformers per Racket - // https://github.com/ion-fusion/fusion-java/issues/73 + // TODO #73 handle rename-transformers per Racket } } else if (isCoreForm(eval, specForm, RENAME_OUT)) diff --git a/runtime/src/test/java/dev/ionfusion/fusion/IdentifierBindingTest.java b/runtime/src/test/java/dev/ionfusion/fusion/IdentifierBindingTest.java index 42a31e0d..818be3e4 100644 --- a/runtime/src/test/java/dev/ionfusion/fusion/IdentifierBindingTest.java +++ b/runtime/src/test/java/dev/ionfusion/fusion/IdentifierBindingTest.java @@ -102,8 +102,7 @@ public void testBasicAndRenameOutRequireBindings() BindingSite topLevelSite = - unsafeIdentifierBinding(eval, - traversal.topLevelReference); + unsafeIdentifierBinding(eval, traversal.topLevelReference); assertBindingAt(3, 9, topLevelSite); assertTrue(topLevelSite.isDefinitionSite()); assertNull(topLevelSite.nextSite()); @@ -115,17 +114,21 @@ public void testBasicAndRenameOutRequireBindings() // to the export site using getModuleBindingInformation after confirming // that this is a required binding. BindingSite moduleProvidedBinding = - unsafeIdentifierBinding(eval, - traversal.moduleReference); + unsafeIdentifierBinding(eval, traversal.moduleReference); assertNull(moduleProvidedBinding.getPosition()); assertTrue(moduleProvidedBinding.isImportSite()); - assertBindingAt(4, 12, - moduleProvidedBinding.nextSite()); + + var exportSite = moduleProvidedBinding.nextSite(); + assertTrue(exportSite.isExportSite()); + assertBindingAt(4, 12, exportSite); + + var defnSite = exportSite.nextSite(); + assertTrue(defnSite.isDefinitionSite()); + assertBindingAt(2, 12, defnSite); BindingSite renameProvidedBinding = - unsafeIdentifierBinding(eval, - traversal.renamedModuleReference); + unsafeIdentifierBinding(eval, traversal.renamedModuleReference); assertNull(renameProvidedBinding.getPosition()); assertTrue(renameProvidedBinding.isImportSite()); assertBindingAt(5, 22, renameProvidedBinding.nextSite());