Skip to content

Commit

Permalink
Expand Elm evaluation engine for module-level bindings
Browse files Browse the repository at this point in the history
+ Add test scenario using module-level binding.
+ Expand productive implementation to make the new test scenario work.
  • Loading branch information
Viir committed Jul 11, 2020
1 parent 8695ed2 commit c196931
Show file tree
Hide file tree
Showing 8 changed files with 479 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ namespace Kalmit.PersistentProcess.WebHost
{
public class Program
{
static public string AppVersionId => "2020-06-28";
static public string AppVersionId => "2020-07-11";
}
}
54 changes: 46 additions & 8 deletions implement/elm-fullstack/ElmEngine/EvaluateElm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,23 @@ static public string GetValueFromEntryPointAsJsonString(
var parsedModule = GetParsedModule(appCodeTree, evaluationRootFilePath);

var entryPointDeclaration =
parsedModule.parsedModule.declarations
.FirstOrDefault(d => d?.value?.function?.declaration?.value?.name?.value == evaluationRootDeclarationName);
FindDeclarationByName(parsedModule.parsedModule, evaluationRootDeclarationName);

if (entryPointDeclaration == null)
throw new Exception("Did not find the declaration for the entry point '" + evaluationRootDeclarationName + "'.");

return EvaluateExpression(entryPointDeclaration?.value?.function?.declaration?.value?.expression?.value).AsJsonString();
return EvaluateExpression(
evaluationContext: parsedModule.parsedModule,
expression: entryPointDeclaration?.value?.function?.declaration?.value?.expression?.value).AsJsonString();
}

static public ElmValue EvaluateExpression(ElmSyntaxJson.Expression expression)
static public ElmSyntaxJson.Node<ElmSyntaxJson.Declaration> FindDeclarationByName(
ElmSyntaxJson.File evaluationContext, string name) =>
evaluationContext.declarations
.FirstOrDefault(d => d?.value?.function?.declaration?.value?.name?.value == name);

static public ElmValue EvaluateExpression(
ElmSyntaxJson.File evaluationContext, ElmSyntaxJson.Expression expression)
{
if (expression.literal != null)
{
Expand All @@ -40,24 +47,45 @@ static public ElmValue EvaluateExpression(ElmSyntaxJson.Expression expression)
}

if (expression.operatorapplication != null)
return EvaluateOperatorApplication(expression.operatorapplication);
return EvaluateOperatorApplication(evaluationContext, expression.operatorapplication);

if (expression.functionOrValue != null)
return EvaluateFunctionOrValue(evaluationContext, expression.functionOrValue);

throw new Exception("Unsupported expression type: " + expression.type);
}

static public ElmValue EvaluateOperatorApplication(ElmSyntaxJson.OperatorApplicationExpression operatorApplication)
static public ElmValue EvaluateOperatorApplication(
ElmSyntaxJson.File evaluationContext, ElmSyntaxJson.OperatorApplicationExpression operatorApplication)
{
if (operatorApplication.@operator == "++")
{
return
ElmValue.OperationConcat(
left: EvaluateExpression(operatorApplication.left.value),
right: EvaluateExpression(operatorApplication.right.value));
left: EvaluateExpression(evaluationContext, operatorApplication.left.value),
right: EvaluateExpression(evaluationContext, operatorApplication.right.value));
}

throw new Exception("Unsupported operator: '" + operatorApplication.@operator + "'");
}

static public ElmValue EvaluateFunctionOrValue(
ElmSyntaxJson.File evaluationContext, ElmSyntaxJson.FunctionOrValueExpression functionOrValue)
{
if (0 < functionOrValue.moduleName.Count)
throw new NotImplementedException("Reaching in other modules is not implemented yet.");

var declaration =
FindDeclarationByName(evaluationContext, functionOrValue.name);

if (declaration == null)
throw new Exception("Did not find declaration for '" + functionOrValue.name + "'. This should not compile.");

return EvaluateExpression(
evaluationContext,
declaration?.value?.function?.declaration?.value?.expression?.value);
}

static (string elmSyntaxJson, ElmSyntaxJson.File parsedModule) GetParsedModule(
Composition.TreeComponent appCodeTree,
IImmutableList<string> filePath)
Expand Down Expand Up @@ -205,6 +233,8 @@ public class Expression
public string literal;

public OperatorApplicationExpression operatorapplication;

public FunctionOrValueExpression functionOrValue;
}

// https://github.com/stil4m/elm-syntax/blob/551248d79d4b0b2ecbf5bb9b7bbad2f52cf01634/src/Elm/Syntax/Expression.elm#L313-L320
Expand All @@ -219,6 +249,14 @@ public class OperatorApplicationExpression
public Node<Expression> right;
}

// https://github.com/stil4m/elm-syntax/blob/783e85f051ac0259078dadf1cb948c8cc9a27413/src/Elm/Syntax/Expression.elm#L240-L246
public class FunctionOrValueExpression
{
public IReadOnlyList<string> moduleName;

public string name;
}

// https://github.com/stil4m/elm-syntax/blob/551248d79d4b0b2ecbf5bb9b7bbad2f52cf01634/src/Elm/Syntax/Infix.elm#L54-L66
public enum InfixDirection
{
Expand Down
4 changes: 2 additions & 2 deletions implement/elm-fullstack/elm-fullstack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>elm_fullstack</RootNamespace>
<AssemblyName>elm-fullstack</AssemblyName>
<AssemblyVersion>2020.0628.0.0</AssemblyVersion>
<FileVersion>2020.0628.0.0</FileVersion>
<AssemblyVersion>2020.0711.0.0</AssemblyVersion>
<FileVersion>2020.0711.0.0</FileVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"Ok": {
"moduleDefinition": {
"range": [
1,
1,
1,
39
],
"value": {
"type": "normal",
"normal": {
"moduleName": {
"range": [
1,
8,
1,
12
],
"value": [
"Main"
]
},
"exposingList": {
"range": [
1,
13,
1,
39
],
"value": {
"type": "explicit",
"explicit": [
{
"range": [
1,
23,
1,
38
],
"value": {
"type": "function",
"function": {
"name": "evaluation_root"
}
}
}
]
}
}
}
}
},
"imports": [],
"declarations": [
{
"range": [
4,
1,
6,
24
],
"value": {
"type": "function",
"function": {
"documentation": null,
"signature": {
"range": [
4,
1,
4,
25
],
"value": {
"name": {
"range": [
4,
1,
4,
16
],
"value": "evaluation_root"
},
"typeAnnotation": {
"range": [
4,
19,
4,
25
],
"value": {
"type": "typed",
"typed": {
"moduleNameAndName": {
"range": [
4,
19,
4,
25
],
"value": {
"moduleName": [],
"name": "String"
}
},
"args": []
}
}
}
}
},
"declaration": {
"range": [
5,
1,
6,
24
],
"value": {
"name": {
"range": [
5,
1,
5,
16
],
"value": "evaluation_root"
},
"arguments": [],
"expression": {
"range": [
6,
5,
6,
24
],
"value": {
"type": "literal",
"literal": "just a literal ✔️"
}
}
}
}
}
}
}
],
"comments": []
}
}
Loading

0 comments on commit c196931

Please sign in to comment.