Skip to content

Commit

Permalink
Implement a concept of constant common variables (half of #46)
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Nov 5, 2011
1 parent 1491987 commit eb2bc3c
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 6 deletions.
4 changes: 3 additions & 1 deletion lib/CodeGen.cs
Expand Up @@ -3737,7 +3737,9 @@ public class DowncallReceiver : CallReceiver {
if (li is LIHint) {
((LIHint)li).var.v = v;
} else if (li is LICommon) {
li.Set(null, v);
StashEnt hkey = Kernel.currentGlobals[((LICommon)li).hkey];
hkey.constant = true;
hkey.v = v;
} else {
return new Exception("cannot bind constant value");
}
Expand Down
18 changes: 14 additions & 4 deletions lib/Kernel.cs
Expand Up @@ -326,13 +326,17 @@ public class StashEnt : IFreeze {
public Variable v;
public string file;
public int line;
public bool constant;

public void Bind(Variable v) {
if (constant)
throw new NieczaException("Binding of constant common variable");
this.v = v;
}

void IFreeze.Freeze(FreezeBuffer fb) {
fb.Byte((byte)SerializationCode.StashEnt);
fb.Byte((byte)(constant ? 1 : 0));
fb.ObjRef(v);
fb.String(file);
fb.Int(line);
Expand All @@ -341,6 +345,7 @@ public class StashEnt : IFreeze {
internal static StashEnt Thaw(ThawBuffer tb) {
StashEnt r = new StashEnt();
tb.Register(r);
r.constant = tb.Byte() != 0;
r.v = (Variable)tb.ObjRef();
r.file = tb.String();
r.line = tb.Int();
Expand Down Expand Up @@ -849,22 +854,26 @@ public sealed class RuntimeUnit : IFreeze {
bool nseod = nseo.IsDefined();
bool oseod = oseo.IsDefined();
// lowest priority are empty common symbols
if (nse.v.rw && !nseod || IsEmptyAggr(nse.v)) {
if (nse.v.rw && !nseod || !nse.constant && IsEmptyAggr(nse.v)) {
nse = ose;
return null;
}
if (ose.v.rw && !oseod || IsEmptyAggr(ose.v)) {
if (ose.v.rw && !oseod || !ose.constant && IsEmptyAggr(ose.v)) {
return null;
}

// no conflict if items are identical
if (ose.v == nse.v || !ose.v.rw && !nse.v.rw && oseo == nseo) {
if (ose.v == nse.v || !ose.v.rw && !nse.v.rw &&
ose.v.islist == nse.v.islist && oseo == nseo) {
nse = ose;
return null;
}

// no conflict if items are simple packages with the same who
if (!ose.v.rw && !oseod && !nse.v.rw && !nseod &&
// note that this will effectively change a constant, but these
// packages are observationally identical barring &infix:<does>
// (mis)use
if (ose.constant && !oseod && nse.constant && !nseod &&
(oseo.mo.mo.isPackage || nseo.mo.mo.isPackage) &&
oseo.mo.who.Isa(Kernel.StashMO) &&
nseo.mo.who.Isa(Kernel.StashMO) &&
Expand All @@ -884,6 +893,7 @@ public sealed class RuntimeUnit : IFreeze {
string file, int line) {
string key = (char)who.Length + who + name;
StashEnt nse = new StashEnt();
nse.constant = (var != null);
if (var == null)
var = MakeAppropriateVar(name);
nse.v = var;
Expand Down
2 changes: 1 addition & 1 deletion lib/Serialize.cs
Expand Up @@ -64,7 +64,7 @@ struct ObjRef {
internal static HashAlgorithm NewHash() { return new SHA256Managed(); }

static readonly string signature = "Niecza-Serialized-Module";
static readonly int version = 4;
static readonly int version = 5;

// Routines for use by serialization code
public bool CheckWriteObject(SerUnit into, object o,
Expand Down

0 comments on commit eb2bc3c

Please sign in to comment.