Skip to content

Commit

Permalink
Begin implementing Bytes in the Elm compiler and kernel libraries
Browse files Browse the repository at this point in the history
+ Expand the Elm value model to support values representing sequences of bytes corresponding to the `Bytes.Bytes` type.
+ Begin implementing the `Bytes.Encode`  Elm kernel module.
+ Begin to implement the `Bytes.Decode`  Elm kernel module.
+ Automate tests using the first encoding and decoding implementations.
  • Loading branch information
Viir committed Sep 29, 2024
1 parent 4cc43aa commit 065ac00
Show file tree
Hide file tree
Showing 34 changed files with 552 additions and 136 deletions.
38 changes: 38 additions & 0 deletions implement/Pine.Core/ElmInteractive/ElmValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type ElmValue
| ElmString String
| ElmTag String (List ElmValue)
| ElmRecord (List ( String, ElmValue ))
| ElmBytes Bytes
| ElmFloat BigInt.BigInt BigInt.BigInt
| ElmInternal String
Expand All @@ -37,6 +38,8 @@ override public string ToString() =>

public const string ElmRecordTypeTagName = "Elm_Record";

public const string ElmBytesTypeTagName = "Elm_Bytes";

public const string ElmStringTypeTagName = "String";

public const string ElmSetTypeTagName = "Set_elm_builtin";
Expand All @@ -50,6 +53,9 @@ override public string ToString() =>
public static readonly PineValue ElmRecordTypeTagNameAsValue =
PineValueAsString.ValueFromString(ElmRecordTypeTagName);

public static readonly PineValue ElmBytesTypeTagNameAsValue =
PineValueAsString.ValueFromString(ElmBytesTypeTagName);

public static readonly PineValue ElmStringTypeTagNameAsValue =
PineValueAsString.ValueFromString(ElmStringTypeTagName);

Expand Down Expand Up @@ -364,6 +370,35 @@ public override string ToString() =>
Fields.FirstOrDefault(field => field.FieldName == fieldName).Value;
}

/// <summary>
/// Elm Bytes type from https://package.elm-lang.org/packages/elm/bytes/latest/
/// </summary>
public record ElmBytes(ReadOnlyMemory<byte> Value)
: ElmValue
{
/// <summary>
/// The number of contained nodes is always zero for the 'Bytes' variant.
/// </summary>
public override int ContainedNodesCount { get; } = 0;


/// <inheritdoc/>
public virtual bool Equals(ElmBytes? otherBytes)
{
if (otherBytes is null)
return false;

if (Value.Length != otherBytes.Value.Length)
return false;

return Value.Span.SequenceEqual(otherBytes.Value.Span);
}

/// <inheritdoc/>
public override int GetHashCode() =>
Value.GetHashCode();
}

/// <summary>
/// The Elm compiler included with Pine models the 'Float' type from Elm as a rational number,
/// expressed as the quotient or fraction ⁠of two integers, a numerator and a denominator.
Expand Down Expand Up @@ -503,6 +538,9 @@ public static (string expressionString, bool needsParens) RenderAsElmExpression(
ElmTag tag =>
ElmTagAsExpression(tag.TagName, tag.Arguments),

ElmBytes bytes =>
("<" + bytes.Value.Length + " bytes>", needsParens: false),

ElmFloat elmFloat =>
(Convert.ToString(
(double)elmFloat.Numerator / (double)elmFloat.Denominator,
Expand Down
26 changes: 26 additions & 0 deletions implement/Pine.Core/ElmInteractive/ElmValueEncoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ public static Result<string, ElmValue> PineListValueAsElmValue(PineValue.ListVal
}
}

{
// case of Bytes.Bytes

if (listValue.Elements[0] == ElmValue.ElmBytesTypeTagNameAsValue)
{
var tagArgumentsValue = listValue.Elements[1];

if (tagArgumentsValue is not PineValue.ListValue tagArgumentsList)
return "Failed to convert value under Bytes tag: Expected a list of tag arguments";

if (tagArgumentsList.Elements.Count is not 1)
return "Failed to convert value under Bytes tag: Expected a list of tag arguments with single item";

if (tagArgumentsList.Elements[0] is not PineValue.BlobValue blobValue)
return "Failed to convert value under Bytes tag: Expected blob value in tag argument";

return new ElmValue.ElmBytes(blobValue.Bytes);
}
}

{
// Optimize for the case of an Elm Float.

Expand Down Expand Up @@ -332,6 +352,7 @@ public static Result<string, ElmValue> PineListValueAsElmValue(PineValue.ListVal
recordFields[i] = (fieldName.Value, fieldValueOk.Value);
continue;
}

return "Failed decoding field value: " + fieldValueResult;
}

Expand Down Expand Up @@ -450,6 +471,11 @@ [.. elmList.Elements.Select(item => ElmValueAsPineValue(item, reusableEncoding))
ElmRecordAsPineValue(
[.. elmRecord.Fields.Select(field => (field.FieldName, ElmValueAsPineValue(field.Value, reusableEncoding)))]),

ElmValue.ElmBytes elmBytes =>
PineValue.List(
[ElmValue.ElmBytesTypeTagNameAsValue,
PineValue.List([PineValue.Blob(elmBytes.Value)])]),

ElmValue.ElmFloat elmFloat =>
PineValue.List(
[ElmValue.ElmFloatTypeTagNameAsValue,
Expand Down
1 change: 1 addition & 0 deletions implement/Pine.Core/PopularValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ from c2 in Enumerable.Range(0, 128)
private static IEnumerable<string> PopularStringsSource =>
[
"Elm_Record",
"Elm_Bytes",

"Basics",
"List",
Expand Down
11 changes: 11 additions & 0 deletions implement/pine/ElmTime/compile-elm-program/src/ElmCompiler.elm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module ElmCompiler exposing
, compilationAndEmitStackFromModulesInCompilation
, compileElmSyntaxExpression
, compileElmSyntaxFunction
, elmBytesTypeTagNameAsValue
, elmFloatTypeTagName
, elmRecordTypeTagName
, elmRecordTypeTagNameAsValue
Expand Down Expand Up @@ -142,6 +143,16 @@ elmRecordTypeTagNameAsValue =
Pine.valueFromString elmRecordTypeTagName


elmBytesTypeTagName : String
elmBytesTypeTagName =
"Elm_Bytes"


elmBytesTypeTagNameAsValue : Pine.Value
elmBytesTypeTagNameAsValue =
Pine.valueFromString elmBytesTypeTagName


elmFloatTypeTagName : String
elmFloatTypeTagName =
"Elm_Float"
Expand Down
Loading

0 comments on commit 065ac00

Please sign in to comment.