Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ SyntaxSymbol predefine(SyntaxSymbol identifier, SyntaxValue formForErrors)
}

/**
* Creates or updates a namespace-level binding.
* Creates or updates a namespace-level binding and infers the object's name.
* Allows rebinding of existing names!
*
* @param value must not be null
Expand Down
56 changes: 16 additions & 40 deletions runtime/src/main/java/dev/ionfusion/fusion/TopLevelNamespace.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package dev.ionfusion.fusion;

import static dev.ionfusion.fusion.FusionVoid.voidValue;
import static dev.ionfusion.fusion.NamedValue.inferObjectName;
import static dev.ionfusion.fusion.ResultFailure.makeResultError;
import static dev.ionfusion.fusion.UnboundIdentifierException.makeUnboundError;

Expand Down Expand Up @@ -252,6 +251,14 @@ public BaseSymbol getDefinedName(int address)
throw new UnsupportedOperationException();
}

void define(SyntaxSymbol id, Object value)
throws FusionException
{
SyntaxSymbol boundId = predefine(id, id);
TopLevelDefinedBinding binding = (TopLevelDefinedBinding) boundId.getBinding();
bind(binding, value);
}


//========================================================================
// Compiled Forms
Expand All @@ -273,31 +280,20 @@ public Object doEval(Evaluator eval, Store store)
throws FusionException
{
Object value = eval.eval(store, myValueForm);
value = processValue(eval, store, value);
eval.checkSingleResult(value, "top-level definition");

TopLevelNamespace ns = (TopLevelNamespace) store.namespace();
SyntaxSymbol boundId = ns.predefine(myId, myId);
TopLevelDefinedBinding binding = (TopLevelDefinedBinding) boundId.getBinding();

ns.set(binding.myAddress, value);

inferObjectName(value, myId.getName());
ns.define(myId, value);

return voidValue(eval);
}

Object processValue(Evaluator eval, Store store, Object value)
throws FusionException
{
eval.checkSingleResult(value, "top-level definition");
return value;
}
}


/**
* Interprets non-single-binding {@code define_values} at top-level.
* Single-binding forms are interpreted by {@link CompiledTopDefine}.
* Zero-binding forms are handled here.
*/
static final class CompiledTopDefineValues
implements CompiledForm
Expand All @@ -307,6 +303,7 @@ static final class CompiledTopDefineValues

CompiledTopDefineValues(SyntaxSymbol[] ids, CompiledForm valuesForm)
{
assert ids.length != 1;
myIds = ids;
myValuesForm = valuesForm;
}
Expand All @@ -319,13 +316,8 @@ public Object doEval(Evaluator eval, Store store)

TopLevelNamespace ns = (TopLevelNamespace) store.namespace();

int expectedCount = myIds.length;
if (expectedCount == 1)
{
eval.checkSingleResult(values, "top-level definition");
defineAndBind(ns, 0, values);
}
else if (values instanceof Object[])
int expectedCount = myIds.length; // != 1
if (values instanceof Object[])
{
Object[] vals = (Object[]) values;
int actualCount = vals.length;
Expand All @@ -339,33 +331,17 @@ else if (values instanceof Object[])

for (int i = 0; i < expectedCount; i++)
{
Object value = vals[i];
defineAndBind(ns, i, value);
ns.define(myIds[i], vals[i]);
}
}
else
{
String expectation =
expectedCount + " results but received 1";
String expectation = expectedCount + " results but received 1";
throw makeResultError(eval, "top-level definition", expectation, values);
}

return voidValue(eval);
}

private void defineAndBind(TopLevelNamespace ns, int i, Object value)
throws FusionException
{
SyntaxSymbol boundId = myIds[i];
boundId = ns.predefine(boundId, boundId);

TopLevelDefinedBinding binding =
(TopLevelDefinedBinding) boundId.getBinding();

ns.set(binding.myAddress, value);

inferObjectName(value, boundId.getName());
}
}


Expand Down
Loading