Skip to content

Commit

Permalink
Added refEquals intrinsic.
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeStrout committed Feb 1, 2023
1 parent b74e3dd commit 532424a
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 3 deletions.
27 changes: 27 additions & 0 deletions MiniScript-cpp/src/MiniScript/MiniscriptIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,28 @@ namespace MiniScript {
return IntrinsicResult::Null;
}
}

static IntrinsicResult intrinsic_refEquals(Context *context, IntrinsicResult partialResult) {
Value a = context->GetVar("a");
Value b = context->GetVar("b");
bool result;
if (a.IsNull()) {
result = (b.IsNull());
} else if (a.type == ValueType::Number) {
result = (b.type == ValueType::Number && a.DoubleValue() == b.DoubleValue());
} else if (a.type == ValueType::String) {
result = (b.type == ValueType::String && a.RefEquals(b));
} else if (a.type == ValueType::List) {
result = (b.type == ValueType::List && a.RefEquals(b));
} else if (a.type == ValueType::Map) {
result = (b.type == ValueType::Map && a.RefEquals(b));
} else if (a.type == ValueType::Function) {
result = (b.type == ValueType::Function && a.RefEquals(b));
} else {
result = a.RefEquals(b);
}
return IntrinsicResult(Value::Truth(result));
}

static IntrinsicResult intrinsic_remove(Context *context, IntrinsicResult partialResult) {
Value self = context->GetVar("self");
Expand Down Expand Up @@ -995,6 +1017,11 @@ namespace MiniScript {
f->AddParam("step");
f->code = &intrinsic_range;

f = Intrinsic::Create("refEquals");
f->AddParam("a");
f->AddParam("b");
f->code = &intrinsic_refEquals;

f = Intrinsic::Create("remove");
f->AddParam("self");
f->AddParam("k");
Expand Down
4 changes: 2 additions & 2 deletions MiniScript-cpp/src/ShellIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ static IntrinsicResult intrinsic_fopen(Context *context, IntrinsicResult partial
Value modeVal = context->GetVar("mode");
String mode = modeVal.ToString();
FILE *handle;
if (modeVal.IsNull() || mode.empty() || mode == "rw+") {
if (modeVal.IsNull() || mode.empty() || mode == "rw+" || mode == "r+") {
// special case: open for reading/updating, creating it if it doesn't exist
handle = fopen(path.c_str(), "r+");
if (handle == NULL) handle = fopen(path.c_str(), "w+");
Expand Down Expand Up @@ -910,7 +910,7 @@ void AddShellIntrinsics() {

i_fopen = Intrinsic::Create("");
i_fopen->AddParam("path");
i_fopen->AddParam("mode");
i_fopen->AddParam("mode", "r+");
i_fopen->code = &intrinsic_fopen;

i_fclose = Intrinsic::Create("");
Expand Down
29 changes: 29 additions & 0 deletions MiniScript-cs/MiniscriptIntrinsics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,35 @@ public static void InitIfNeeded() {
return new Intrinsic.Result(new ValList(values));
};

// refEquals
// Tests whether two values refer to the very same object (rather than
// merely representing the same value). For numbers, this is the same
// as ==, but for strings, lists, and maps, it is reference equality.
f = Intrinsic.Create("refEquals");
f.AddParam("a");
f.AddParam("b");
f.code = (context, partialResult) => {
Value a = context.GetLocal("a");
Value b = context.GetLocal("b");
bool result = false;
if (a == null) {
result = (b == null);
} else if (a is ValNumber) {
result = (b is ValNumber && a.DoubleValue() == b.DoubleValue());
} else if (a is ValString) {
result = (b is ValString && ReferenceEquals( ((ValString)a).value, ((ValString)b).value ));
} else if (a is ValList) {
result = (b is ValList && ReferenceEquals( ((ValList)a).values, ((ValList)b).values ));
} else if (a is ValMap) {
result = (b is ValMap && ReferenceEquals( ((ValMap)a).map, ((ValMap)b).map ));
} else if (a is ValFunction) {
result = (b is ValFunction && ReferenceEquals( ((ValFunction)a).function, ((ValFunction)b).function ));
} else {
result = (a.Equality(b) >= 1);
}
return new Intrinsic.Result(ValNumber.Truth(result));
};

// remove
// Removes part of a list, map, or string. Exact behavior depends on
// the data type of self:
Expand Down
4 changes: 3 additions & 1 deletion MiniScript-cs/MiniscriptTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public virtual string CodeForm(TAC.Machine vm, int recursionLimit=-1) {
/// Check whether this Value is equal to another Value.
/// </summary>
/// <param name="rhs">other value to compare to</param>
/// <returns>1if these values are considered equal; 0 if not equal; 0.5 if unsure</returns>
/// <returns>1 if these values are considered equal; 0 if not equal; 0.5 if unsure</returns>
public abstract double Equality(Value rhs);

/// <summary>
Expand Down Expand Up @@ -211,6 +211,8 @@ protected bool RecursiveEqual(Value rhs) {
var newPair = new ValuePair() { a = valFromA, b = valFromB };
if (!visited.Contains(newPair)) toDo.Push(newPair);
}
} else if (pair.a == null || pair.b == null) {
return pair.a == null && pair.b == null;
} else {
// No other types can recurse, so we can safely do:
if (pair.a.Equality(pair.b) == 0) return false;
Expand Down
21 changes: 21 additions & 0 deletions TestSuite.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,27 @@ hellofoo
[1, 2, 3, 1, 2, 3]
[1, 2, 3]
======================================================================
==== Test the refEquals intrinsic
a = {"x":42}
b = {"x":42}
c = a
print refEquals(a,b)
print refEquals(a,c)
print refEquals(b,c)
a = [1,2,3]
b = [1,2,3]
c = a
print refEquals(a,b)
print refEquals(a,c)
print refEquals(b,c)
----------------------------------------------------------------------
0
1
0
0
1
0
======================================================================
==== Test the split intrinsic
print split("Eat, pray, love", ", ")
print split("...foo...bar...", "...")
Expand Down

0 comments on commit 532424a

Please sign in to comment.