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
8 changes: 4 additions & 4 deletions CSharp/Interpreter/ArcscriptExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,10 @@ private static DoubleValues GetDoubleValues(object first, object second) {

internal static bool GetBoolValue(object value)
{
if (value.GetType() == typeof(bool)) { return (bool)value; }
if (value.GetType() == typeof(string)) { return ((string)value).Length > 0; }
if (value.GetType() == typeof(int)) { return (int)value > 0; }
if (value.GetType() == typeof(double)) { return (double)value > 0; }
if (value is bool b) { return b; }
if (value is string s) { return s.Length > 0; }
if (value is int i) { return i > 0; }
if (value is double d) { return d > 0; }
return false;
}
}
Expand Down
46 changes: 28 additions & 18 deletions CSharp/Interpreter/ArcscriptFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Arcweave.Interpreter.INodes;
using Arcweave.Project;

namespace Arcweave.Interpreter
{
Expand All @@ -13,21 +14,29 @@ public class Functions
private ArcscriptState state;
public Dictionary<string, Func<IList<object>, object>> functions { get; private set; } = new Dictionary<string, Func<IList<object>, object>>();

public Dictionary<string, Type> returnTypes = new Dictionary<string, Type>()
public class FunctionDefinition
{
{ "sqrt", typeof (double) },
{ "sqr", typeof (double) },
{ "abs", typeof (double) },
{ "random", typeof (double) },
{ "roll", typeof (int) },
{ "show", typeof (string) },
{ "reset", typeof (void) },
{ "resetAll", typeof (void) },
{ "round", typeof (int) },
{ "min", typeof (double) },
{ "max", typeof (double) },
{ "visits", typeof (int) },
{ "resetVisits", typeof (void) },
public int? MinArgs { get; set; }
public int? MaxArgs { get; set; }
public Type ArgumentsType { get; set; }
public Type ReturnType { get; set; }
}

public static Dictionary<string, FunctionDefinition> FunctionDefinitions =
new() {
{ "abs", new FunctionDefinition { MinArgs=1, MaxArgs=1, ReturnType = typeof(int)} },
{ "max", new FunctionDefinition { MinArgs=2, ReturnType = typeof(double)} },
{ "min", new FunctionDefinition { MinArgs=2, ReturnType = typeof(double)} },
{ "random", new FunctionDefinition { MinArgs=0, MaxArgs=0, ReturnType = typeof(double)} },
{ "roll", new FunctionDefinition { MinArgs=1, MaxArgs=2, ReturnType = typeof(int)} },
{ "round", new FunctionDefinition { MinArgs=1, MaxArgs=1, ReturnType = typeof(int)} },
{ "sqr", new FunctionDefinition { MinArgs=1, MaxArgs=1, ReturnType = typeof(double)} },
{ "sqrt", new FunctionDefinition { MinArgs=1, MaxArgs=1, ReturnType = typeof(double)} },
{ "visits", new FunctionDefinition { MinArgs=0, MaxArgs=1, ReturnType = typeof(int)} },
{ "show", new FunctionDefinition { MinArgs=1, ReturnType = typeof(string)} },
{ "reset", new FunctionDefinition { MinArgs=1, ArgumentsType = typeof(Variable), ReturnType = typeof(void)} },
{ "resetAll", new FunctionDefinition { MinArgs=0, ArgumentsType = typeof(Variable), ReturnType = typeof(void)} },
{ "resetVisits", new FunctionDefinition { MinArgs=0, MaxArgs = 0, ReturnType = typeof(void)} },
};

public Functions(string elementId, IProject project, ArcscriptState state) {
Expand Down Expand Up @@ -152,7 +161,7 @@ public object Show(IList<object> args) {

public object Reset(IList<object> args) {
foreach (IVariable argument in args ) {
state.SetVarValue(argument.Name, argument.DefaultValue);
state.SetVarValue(argument, argument.DefaultValue);
}
return null;
}
Expand All @@ -164,7 +173,7 @@ public object ResetAll(IList<object> args) {
}
foreach ( IVariable variable in this._project.Variables ) {
if ( !variableNames.Contains(variable.Name) ) {
state.SetVarValue(variable.Name, variable.DefaultValue);
state.SetVarValue(variable, variable.DefaultValue);
}
}
return null;
Expand All @@ -179,12 +188,13 @@ public object Round(IList<object> args) {
public object Min(IList<object> args)
{
IList<Expression> arguments = args.Cast<Expression>().ToList();
return arguments.Min();

return arguments.Min().Value;
}

public object Max(IList<object> args) {
IList<Expression> arguments = args.Cast<Expression>().ToList();
return arguments.Max();
return arguments.Max().Value;
}

public object Visits(IList<object> args) {
Expand Down
106 changes: 49 additions & 57 deletions CSharp/Interpreter/ArcscriptParserBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,41 @@
using System.IO;
using System.Linq;
using Arcweave.Interpreter.INodes;
using Arcweave.Project;

namespace Arcweave.Interpreter
{
public class ArcscriptParserBase : Parser
{
private class FunctionArgs
{
public int? MinArgs { get; set; }
public int? MaxArgs { get; set; }
}

private Dictionary<string, FunctionArgs> ArcscriptFunctions;
private protected IProject Project { get; private set; }

private protected List<string> VariableNames = new List<string>();
internal int currentLine;
internal int openTagEndPos;
public ArcscriptParserBase(ITokenStream input) : base(input) {
var functions = new Dictionary<string, FunctionArgs>()
{
{ "abs", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "max", new FunctionArgs { MinArgs=2 } },
{ "min", new FunctionArgs { MinArgs=2 } },
{ "random", new FunctionArgs { MinArgs=0, MaxArgs=0 } },
{ "roll", new FunctionArgs { MinArgs=1, MaxArgs=2 } },
{ "round", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "sqr", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "sqrt", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "visits", new FunctionArgs { MinArgs=0, MaxArgs=1 } },
{ "show", new FunctionArgs { MinArgs=1 } },
{ "reset", new FunctionArgs { MinArgs=1 } },
{ "resetAll", new FunctionArgs { MinArgs=0 } },
{ "resetVisits", new FunctionArgs { MinArgs=0, MaxArgs = 0} },
};

this.ArcscriptFunctions = functions;


public ArcscriptParserBase(ITokenStream input) : base(input)
{
}

public ArcscriptParserBase(ITokenStream input, TextWriter output, TextWriter errorOutput) : base(input, output, errorOutput) {
var functions = new Dictionary<string, FunctionArgs>()
public ArcscriptParserBase(ITokenStream input, TextWriter output, TextWriter errorOutput) : base(input, output, errorOutput)
{
{ "abs", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "max", new FunctionArgs { MinArgs=2 } },
{ "min", new FunctionArgs { MinArgs=2 } },
{ "random", new FunctionArgs { MinArgs=0, MaxArgs=0 } },
{ "roll", new FunctionArgs { MinArgs=1, MaxArgs=2 } },
{ "round", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "sqr", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "sqrt", new FunctionArgs { MinArgs=1, MaxArgs=1 } },
{ "visits", new FunctionArgs { MinArgs=0, MaxArgs=1 } },
{ "show", new FunctionArgs { MinArgs=1 } },
{ "reset", new FunctionArgs { MinArgs=1 } },
{ "resetAll", new FunctionArgs { MinArgs=0 } },
{ "resetVisits", new FunctionArgs { MinArgs=0, MaxArgs = 0} },
};

this.ArcscriptFunctions = functions;
}

public void SetProject(IProject project) {
this.Project = project;
foreach (var projectVariable in project.Variables)
{
VariableNames.Add(projectVariable.Name);
}
foreach (var projectBoard in project.Boards)
{
if (projectBoard.Variables == null) continue;
foreach (var projectBoardVariable in projectBoard.Variables)
{
VariableNames.Add(projectBoard.CustomId + "." + projectBoardVariable.Name);
}
}
}

public override string[] RuleNames => throw new System.NotImplementedException();
Expand All @@ -71,9 +46,10 @@ public void SetProject(IProject project) {

public override string GrammarFileName => throw new System.NotImplementedException();

public bool assertVariable(IToken variable) {
var variableName = variable.Text;
var found = this.Project.Variables.First(x => x.Name == variableName);
public bool assertVariable(ArcscriptParser.IdentifierContext identifierContext) {
var variableName = identifierContext.GetText();

var found = VariableNames.First(name => name == variableName);
if ( found != null ) {
return false;
}
Expand Down Expand Up @@ -105,26 +81,42 @@ public bool assertMention(IList<ArcscriptParser.Mention_attributesContext> attrC
return true;
}

public bool assertFunctionArguments(IToken fname, ArcscriptParser.Argument_listContext argumentList) {
public bool assertFunctionArguments(IToken fname, ArcscriptParser.Argument_listContext argumentListContext) {
int argListLength = 0;
if ( argumentList != null && argumentList.argument() != null ) {
argListLength = argumentList.argument().Length;
if ( argumentListContext != null && argumentListContext.argument() != null ) {
argListLength = argumentListContext.argument().Length;
}
var min = this.ArcscriptFunctions[fname.Text].MinArgs;
var max = this.ArcscriptFunctions[fname.Text].MaxArgs;
var min = Functions.FunctionDefinitions[fname.Text].MinArgs;
var max = Functions.FunctionDefinitions[fname.Text].MaxArgs;
var argType = Functions.FunctionDefinitions[fname.Text].ArgumentsType;
if ( ( min != null && argListLength < min ) || ( max != null && argListLength > max ) ) {
throw new RecognitionException("Incorrect number of arguments for function " + fname.Text, this, this.InputStream, this.Context);
}

if (argType != null && argumentListContext != null && argumentListContext.argument() != null)
{
if (argType == typeof(Variable))
{
throw new RecognitionException("Function " + fname.Text + " accepts variables as arguments", this, this.InputStream, this.Context);
}
}

return true;
}

public bool assertFunctionArguments(IToken fname, ArcscriptParser.Variable_listContext variable_List) {
int varListLength = variable_List.VARIABLE().Length;
var min = this.ArcscriptFunctions[fname.Text].MinArgs;
var max = this.ArcscriptFunctions[fname.Text].MaxArgs;
if ( ( min != null && varListLength < min ) || ( max != null && varListLength > max ) ) {
public bool assertFunctionArguments(IToken fname, ArcscriptParser.Identifier_listContext identifierListContext) {
int identifierListLength = 0;
if (identifierListContext != null && identifierListContext.identifier() != null)
{
identifierListLength = identifierListContext.identifier().Length;
}

var min = Functions.FunctionDefinitions[fname.Text].MinArgs;
var max = Functions.FunctionDefinitions[fname.Text].MaxArgs;
if ( ( min != null && identifierListLength < min ) || ( max != null && identifierListLength > max ) ) {
throw new RecognitionException("Incorrect number of arguments for function " + fname.Text, this, this.InputStream, this.Context);
}

return true;
}

Expand Down
51 changes: 44 additions & 7 deletions CSharp/Interpreter/ArcscriptState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ public class ArcscriptState
public ArcscriptOutputs Outputs;
public string currentElement { get; set; }
public IProject project { get; set; }

public Dictionary<string, Variable> Variables { get; } = new Dictionary<string, Variable>();

private System.Action<string> _emit;
public ArcscriptState(string elementId, IProject project, System.Action<string>? emit = null)
{
Outputs = new ArcscriptOutputs();
this.currentElement = elementId;
this.project = project;

this.Variables = project.Variables.ToDictionary(variable => variable.Id, variable => variable);
foreach (var projectBoard in project.Boards)
{
if (projectBoard.Variables == null) continue;
foreach (var projectBoardVariable in projectBoard.Variables)
{
Variables.Add(projectBoardVariable.Id, projectBoardVariable);
}
}

if (emit != null)
{
_emit = emit;
Expand All @@ -30,25 +43,49 @@ public ArcscriptState(string elementId, IProject project, System.Action<string>?
}
}

public IVariable? GetVariable(string name) {
public IVariable? GetVariable(string name, string? scope = null) {
try
{
return this.project.Variables.First(variable => variable.Name == name);
return Variables.Values.FirstOrDefault(variable =>
{
if (scope != null)
{
return variable.Name == name && scope == variable.Parent.CustomId;
}

return variable.Name == name && variable.Parent == null;
});
}
catch (System.InvalidOperationException)
{
return null;
}
}

public object GetVarValue(string name) {
if ( this.VariableChanges.ContainsKey(name) ) {
return VariableChanges[name];
public object GetVarValue(string name, string? scope = null)
{
var v = GetVariable(name, scope);
if (v == null)
{
throw new System.InvalidOperationException($"Variable {name} not found");
}
return this.project.GetVariable(name).ObjectValue;

return this.VariableChanges.ContainsKey(v.Id) ? VariableChanges[v.Id] : v.ObjectValue;
}

public void SetVarValue(string name, object value) { VariableChanges[name] = value; }
public void SetVarValue(IVariable v, object value)
{
VariableChanges[v.Id] = value;
}

public void SetVarValue(ArcscriptVisitor.IdentifierDef identifierDef, object value) {
var v = GetVariable(identifierDef.Name, identifierDef.Scope);
if (v == null)
{
throw new System.InvalidOperationException($"Variable {identifierDef.Name} not found");
}
VariableChanges[v.Id] = value;
}

public void SetVarValues(string[] names, string[] values) {
for ( int i = 0; i < names.Length; i++ ) {
Expand Down
Loading
Loading