preliminary implementation of Zq scripting language for MADI

This commit is contained in:
Michael Becker 2024-12-30 23:23:49 -05:00
parent 9b501f29f6
commit f1d5768b98
43 changed files with 2541 additions and 3 deletions

View File

@ -45,6 +45,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Oms.Server", "mocha-d
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Core.UI.Server", "mocha-dotnet\src\lib\Mocha.Core.UI.Server\Mocha.Core.UI.Server.csproj", "{4D1E2156-B1B5-4D15-B347-1F0E07C95891}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Zq", "mocha-dotnet\src\lib\Mocha.Zq\Mocha.Zq.csproj", "{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Zq.Tests", "mocha-dotnet\tests\Mocha.Zq.Tests\Mocha.Zq.Tests.csproj", "{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Zq.Integration", "mocha-dotnet\src\lib\Mocha.Zq.Integration\Mocha.Zq.Integration.csproj", "{ADD7359E-0E3B-4435-B812-EC961C52DA2A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -83,6 +89,18 @@ Global
{4D1E2156-B1B5-4D15-B347-1F0E07C95891}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D1E2156-B1B5-4D15-B347-1F0E07C95891}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D1E2156-B1B5-4D15-B347-1F0E07C95891}.Release|Any CPU.Build.0 = Release|Any CPU
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98}.Release|Any CPU.Build.0 = Release|Any CPU
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB}.Release|Any CPU.Build.0 = Release|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADD7359E-0E3B-4435-B812-EC961C52DA2A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -106,6 +124,9 @@ Global
{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF} = {B024FD23-7084-4DDF-A185-D58BEE7A006F}
{EB83EE7A-AFFE-4068-B445-9139F2DEA0F6} = {11486802-8136-4958-8B32-FC34630B0306}
{4D1E2156-B1B5-4D15-B347-1F0E07C95891} = {A2C401E9-FED4-43BA-A928-566239894CEE}
{04985CF7-45AA-4C67-9EEC-BDDF2DFC5C98} = {A2C401E9-FED4-43BA-A928-566239894CEE}
{F5D1EF0F-B42F-4237-B08A-7A78143C3ECB} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
{ADD7359E-0E3B-4435-B812-EC961C52DA2A} = {A2C401E9-FED4-43BA-A928-566239894CEE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D28A9CF8-0235-4F8F-865F-C460BDCAE16D}

View File

@ -536,7 +536,13 @@ public abstract class Oms
}
protected abstract void SetInstanceKeyInternal(InstanceHandle target, InstanceKey instanceKey);
protected void SetInstanceKey(InstanceHandle target, InstanceKey instanceKey)
/// <summary>
/// Sets the instance key for the given target instance. Instance Keys must conform to certain rules; namely, the
/// class index of the Instance Key must match the instance index of the instance's parent class.
/// </summary>
/// <param name="target"></param>
/// <param name="instanceKey"></param>
public void SetInstanceKey(InstanceHandle target, InstanceKey instanceKey)
{
SetInstanceKeyInternal(target, instanceKey);
}
@ -1394,7 +1400,7 @@ public abstract class Oms
return value;
}
public Method GetMethod(InstanceHandle forClass, string verb, string name, AccessModifier? accessModifier = null, bool? is_static = null)
public Method GetMethod(InstanceHandle forClass, string? verb, string name, AccessModifier? accessModifier = null, bool? is_static = null)
{
// this really needs to be super fast...
InstanceHandle a_Verb = GetInstance(KnownAttributeGuids.Text.Verb);
@ -1405,7 +1411,7 @@ public abstract class Oms
{
string _verb = GetAttributeValue<string>(method, a_Verb);
string _name = GetAttributeValue<string>(method, a_Name);
if (_verb.Equals(verb) && _name.Equals(name))
if ((verb == null || _verb.Equals(verb)) && _name.Equals(name))
{
return (Method)ConcreteInstanceWrapper.Wrap(this, method);
}
@ -2073,4 +2079,18 @@ public abstract class Oms
}
return value;
}
public InstanceHandle GetInstanceByName(InstanceHandle parentClass, string name)
{
InstanceHandle a_Name = GetInstance(KnownAttributeGuids.Text.Name);
IEnumerable<InstanceHandle> ihs = GetInstancesOf(parentClass);
foreach (InstanceHandle ih in ihs)
{
if ((GetAttributeValue<string>(ih, a_Name)?.Equals(name)).GetValueOrDefault(false))
{
return ih;
}
}
return InstanceHandle.Empty;
}
}

View File

@ -78,6 +78,17 @@ public class OmsMethodBuilder
return new GetAttributeMethod(method);
}
public GetSpecifiedInstancesMethod CreateGetSpecifiedInstancesMethod(InstanceHandle forClassInstance, string verb, string name, WorkSet returnsWorkSet, InstanceHandle specifiedInstance)
{
return CreateGetSpecifiedInstancesMethod(forClassInstance, verb, name, null, false, returnsWorkSet, specifiedInstance);
}
public GetSpecifiedInstancesMethod CreateGetSpecifiedInstancesMethod(InstanceHandle forClassInstance, string verb, string name, AccessModifier accessModifier, bool isStatic, WorkSet returnsWorkSet, InstanceHandle specifiedInstance)
{
GetSpecifiedInstancesMethod meth = CreateGetSpecifiedInstancesMethod(forClassInstance, verb, name, accessModifier, isStatic, returnsWorkSet, new InstanceHandle[] { specifiedInstance });
Oms.SetAttributeValue(meth.Handle, Oms.GetInstance(KnownAttributeGuids.Boolean.Singular), true);
return meth;
}
public GetSpecifiedInstancesMethod CreateGetSpecifiedInstancesMethod(InstanceHandle forClassInstance, string verb, string name, WorkSet returnsWorkSet, InstanceHandle[] specifiedInstances)
{
return CreateGetSpecifiedInstancesMethod(forClassInstance, verb, name, null, false, returnsWorkSet, specifiedInstances);

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
<ProjectReference Include="../Mocha.Core/Mocha.Core.csproj" />
<ProjectReference Include="../Mocha.Zq/Mocha.Zq.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,291 @@
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualBasic;
using Mocha.Core;
using Mocha.Zq.Expressions;
using Mocha.Zq.Methods;
namespace Mocha.Zq.Integration;
public class ZqIntegrator
{
private Oms OMS { get; }
public ZqParser Parser { get; }
public ZqIntegrator(Oms oms)
{
OMS = oms;
Parser = new ZqParser();
}
public object? Evaluate(string text)
{
return Evaluate(Parser.Parse(text));
}
public object? Evaluate(Stream stream)
{
return Evaluate(Parser.Parse(stream));
}
public object? Evaluate(ZqObject? obj)
{
if (obj is ZqClass zql)
{
InstanceHandle ih = OMS.CreateClass(zql.Name);
if (zql.InstanceKey != InstanceKey.Empty)
{
if (zql.InstanceKey.ClassIndex == 1)
{
OMS.SetInstanceKey(ih, zql.InstanceKey);
}
}
InstanceKey parentIK = OMS.GetInstanceKey(ih);
foreach (ZqInstance inst in zql.Instances)
{
InstanceHandle ih2 = OMS.CreateInstanceOf(ih);
if (inst.InstanceKey != InstanceKey.Empty && inst.InstanceKey.ClassIndex == parentIK.InstanceIndex)
{
OMS.SetInstanceKey(ih2, inst.InstanceKey);
}
InstanceHandle a_Name = OMS.GetInstance(KnownAttributeGuids.Text.Name);
if (a_Name != InstanceHandle.Empty)
{
if (inst.Name != null)
{
OMS.SetAttributeValue(ih2, a_Name, inst.Name);
}
}
}
foreach (ZqMethod meth in zql.Functions)
{
if (meth is ZqSimpleReturnMethod gsi)
{
Core.Oop.WorkSet ws = OMS.CreateWorkSet(meth.Name);
if (gsi.ReturnValue is ZqArray)
{
List<InstanceHandle> list = new List<InstanceHandle>();
foreach (ZqObject obj2 in ((ZqArray)gsi.ReturnValue))
{
if (obj2 is ZqVariableReference rr)
{
object r = ResolveVariable(ih, rr.Name);
if (r is InstanceHandle ihret)
{
list.Add(ihret);
}
}
}
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih, null, meth.Name, ws, list.ToArray());
}
else if (gsi.ReturnValue is ZqVariableReference)
{
object r = ResolveVariable(ih, ((ZqVariableReference)gsi.ReturnValue).Name);
if (r is InstanceHandle ihret)
{
OMS.MethodBuilder.CreateGetSpecifiedInstancesMethod(ih, null, meth.Name, ws, ihret);
}
}
}
}
return ih;
}
return null;
}
private object ResolveVariable(InstanceHandle parentClassInstance, string name)
{
InstanceHandle ihret = OMS.GetInstanceByName(parentClassInstance, name);
if (ihret != InstanceHandle.Empty)
{
return ihret;
}
return null;
}
public InstanceHandle GetMethod(string fullyQualifiedName)
{
string[] namespacedName = fullyQualifiedName.Split(new char[] { '.' });
if (namespacedName.Length > 1)
{
if (namespacedName.Length == 2)
{
string className = namespacedName[0];
string methodName = namespacedName[1];
InstanceHandle c = OMS.GetInstanceByName(OMS.GetInstance(KnownInstanceGuids.Classes.Class), className);
IEnumerable<InstanceHandle> ihMethods = OMS.GetRelatedInstances(c, OMS.GetInstance(KnownRelationshipGuids.Class__has__Method));
InstanceHandle a_Name = OMS.GetInstance(KnownAttributeGuids.Text.Name);
foreach (InstanceHandle ihMethod in ihMethods)
{
string name = OMS.GetAttributeValue<string>(ihMethod, a_Name);
if (methodName == name)
{
return ihMethod;
}
}
}
}
else
{
// ??? test this
return OMS.GetInstanceByName(OMS.GetInstance(KnownInstanceGuids.Classes.Method), namespacedName[0]);
}
return InstanceHandle.Empty;
}
public ZqObject? Import(InstanceHandle inst)
{
if (OMS.IsInstanceOf(inst, OMS.GetInstance(KnownInstanceGuids.Classes.Class)))
{
string name = ZqNormalizeName(OMS.GetAttributeValue<string>(inst, OMS.GetInstance(KnownAttributeGuids.Text.Name)));
ZqClass cls = new ZqClass(name);
IEnumerable<InstanceHandle> insts = OMS.GetInstancesOf(inst);
foreach (InstanceHandle inst2 in insts)
{
cls.Instances.Add(new ZqInstance() { InstanceKey = OMS.GetInstanceKey(inst2), Name = ZqNormalizeName(OMS.GetInstanceText(inst2)) });
}
return cls;
}
else if (OMS.IsInstanceOf(inst, OMS.GetInstance(KnownInstanceGuids.Classes.Relationship)))
{
InstanceKey ik = OMS.GetInstanceKey(inst);
InstanceHandle destClass = OMS.GetRelatedInstance(inst, OMS.GetInstance(KnownRelationshipGuids.Relationship__has_destination__Class));
string relTypeName = OMS.GetAttributeValue<string>(inst, OMS.GetInstance(KnownAttributeGuids.Text.RelationshipType));
string destClassName = ZqNormalizeName(OMS.GetInstanceText(destClass));
string name = ZqNormalizeName(relTypeName + destClassName);
bool singular = OMS.GetAttributeValue<bool>(inst, OMS.GetInstance(KnownAttributeGuids.Boolean.Singular));
ZqDataType dt = new ZqDataType(destClassName, !singular);
ZqRelationship rel = new ZqRelationship(name, relTypeName, dt, ik);
return rel;
}
else if (OMS.IsInstanceOf(inst, OMS.GetInstance(KnownInstanceGuids.MethodClasses.GetRelationshipMethod)))
{
string verb = OMS.GetAttributeValue<string>(inst, OMS.GetInstance(KnownAttributeGuids.Text.Verb));
string name = OMS.GetAttributeValue<string>(inst, OMS.GetInstance(KnownAttributeGuids.Text.Name));
string fullName = verb + name;
fullName = ZqNormalizeName(fullName);
InstanceHandle ihReturnsRelationship = OMS.GetRelatedInstance(inst, OMS.GetInstance(KnownRelationshipGuids.Get_Relationship_Method__returns__Relationship));
ZqRelationship rel = (ZqRelationship)Import(ihReturnsRelationship);
return new ZqGetRelationshipMethod(fullName, rel);
}
throw new NotImplementedException();
}
private string ZqNormalizeName(string fullName)
{
return fullName.Replace("-", "_").Replace(" ", "").Replace("(", "_").Replace(")", "_");
}
private string GetFunctionDefinition(ZqMethod method)
{
return String.Format("function {0}({1}) : {2}", method.Name, GenerateCode(method.Parameters), method.ReturnDataType);
}
public string GenerateCode(IEnumerable<ZqParameter> parms)
{
StringBuilder sb = new StringBuilder();
foreach (ZqParameter parm in parms)
{
sb.Append(parm.Name);
if (!parm.DataType.Equals(ZqDataType.None))
{
sb.Append(" : ");
sb.Append(parm.DataType);
}
sb.Append(", ");
}
if (sb.Length > 2)
{
sb.Remove(sb.Length - 2, 2);
}
return sb.ToString();
}
public string GenerateCode(ZqAccessModifier accessModifier)
{
switch (accessModifier)
{
case ZqAccessModifier.None: return String.Empty;
// case ZqAccessModifier.Internal: return "internal";
case ZqAccessModifier.Private: return "private";
case ZqAccessModifier.Protected: return "protected";
// case ZqAccessModifier.ProtectedInternal: return "protected internal";
case ZqAccessModifier.Public: return "public";
}
throw new NotImplementedException();
}
public string GenerateCode(ZqObject? obj)
{
StringBuilder sb = new StringBuilder();
if (obj is ZqClass cls)
{
if (cls.AccessModifier != ZqAccessModifier.None)
{
sb.Append(GenerateCode(cls.AccessModifier));
sb.Append(' ');
}
sb.Append("class ");
sb.Append(cls.Name);
if (cls.InstanceKey != InstanceKey.Empty)
{
sb.Append(", ");
sb.Append(cls.InstanceKey);
}
sb.AppendLine(" {");
if (cls.Attributes.Count > 0)
{
sb.AppendLine("attributes:");
sb.AppendLine();
}
if (cls.Relationships.Count > 0)
{
sb.AppendLine("relationships:");
sb.AppendLine();
}
if (cls.Functions.Count > 0)
{
sb.AppendLine("functions:");
sb.AppendLine();
}
if (cls.Instances.Count > 0)
{
sb.AppendLine("instances:");
foreach (ZqInstance inst in cls.Instances)
{
sb.AppendLine(String.Format("\t{0}, {1}", inst.Name, inst.InstanceKey));
}
}
sb.AppendLine();
sb.AppendLine("}");
}
else if (obj is ZqMethod m)
{
sb.Append(GetFunctionDefinition(m));
sb.Append(" = ");
if (obj is ZqGetRelationshipMethod gr)
{
sb.Append("this.");
sb.Append(gr.Relationship.Name);
}
else if (obj is ZqSimpleReturnMethod m2)
{
sb.Append(m2.ReturnValue);
}
// sb.Append("{");
// sb.Append("}");
}
return sb.ToString();
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace Mocha.Zq.Expressions;
public class ZqLiteral : ZqExpression
{
public object Value { get; }
public ZqLiteral(object value)
{
Value = value;
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Text;
namespace Mocha.Zq.Expressions;
public class ZqVariableReference : ZqExpression
{
public string Name { get; }
public string? ObjectName { get; }
public string PropertyName { get; }
public ZqVariableReference(string name)
{
Name = name;
if (Name.Contains("."))
{
ObjectName = Name.Substring(0, Name.LastIndexOf('.'));
PropertyName = Name.Substring(Name.LastIndexOf('.') + 1);
}
else
{
ObjectName = null;
PropertyName = Name;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
if (ObjectName != null)
{
sb.Append(ObjectName);
sb.Append('.');
}
sb.Append(PropertyName);
return sb.ToString();
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Mocha.Zq;
public interface IZqMethod
{
string Name { get; set; }
ZqDataType ReturnDataType { get; set; }
ZqMethodCall? Executable { get; }
}

View File

@ -0,0 +1,12 @@
using System;
namespace Mocha.Zq.Methods;
public class ZqBuildAttributeMethod : ZqMethod
{
public object? InitialValue { get; set; } = null;
public ZqBuildAttributeMethod(string name, object initialValue) : base(name)
{
InitialValue = initialValue;
}
}

View File

@ -0,0 +1,28 @@
using System;
using MBS.Core.Collections.Generic;
namespace Mocha.Zq.Methods;
public class ZqConditionalSelectAttributeCase
{
public class ZqConditionalSelectAttributeCaseCollection
: System.Collections.ObjectModel.Collection<ZqConditionalSelectAttributeCase>
{
}
public ZqCondition.ZqConditionCollection TrueConditions { get; } = new ZqCondition.ZqConditionCollection();
public ZqCondition.ZqConditionCollection FalseConditions { get; } = new ZqCondition.ZqConditionCollection();
public bool UseAnyCondition { get; set; } = false;
public ZqObject? Result { get; set; } = null;
public ZqConditionalSelectAttributeCase(IEnumerable<ZqCondition> trueConditions, IEnumerable<ZqCondition> falseConditions, bool useAnyCondition, ZqObject? result)
{
TrueConditions.AddRange(trueConditions);
FalseConditions.AddRange(falseConditions);
UseAnyCondition = useAnyCondition;
Result = result;
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace Mocha.Zq.Methods;
public class ZqConditionalSelectAttributeMethod : ZqMethod
{
public ZqConditionalSelectAttributeMethod(string name = null) : base(name) { }
public ZqConditionalSelectAttributeCase.ZqConditionalSelectAttributeCaseCollection Cases { get; } = new ZqConditionalSelectAttributeCase.ZqConditionalSelectAttributeCaseCollection();
}

View File

@ -0,0 +1,15 @@
using System;
namespace Mocha.Zq.Methods;
public class ZqGetRelationshipMethod : ZqMethod
{
public ZqRelationship Relationship { get; }
public ZqGetRelationshipMethod(string name, ZqRelationship rel) : base(name)
{
Relationship = rel;
}
public override ZqDataType ReturnDataType { get => Relationship.DataType; }
}

View File

@ -0,0 +1,13 @@
using System;
using Mocha.Zq.Expressions;
namespace Mocha.Zq.Methods;
public class ZqSimpleReturnMethod : ZqMethod
{
public object ReturnValue { get; }
public ZqSimpleReturnMethod(string name, object returnValue) : base(name)
{
ReturnValue = returnValue;
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
<ProjectReference Include="../Mocha.Core/Mocha.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
namespace Mocha.Zq;
public enum ZqAccessModifier
{
None,
Public,
Protected,
Internal,
ProtectedInternal,
Private
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections;
namespace Mocha.Zq;
public class ZqArray : ZqObject, IEnumerable<ZqObject>
{
public int Size { get; } = 0;
public ZqArray(int size)
{
Size = size;
_ary = new ZqObject[size];
}
private ZqObject[] _ary = new ZqObject[0];
public ZqObject this[int index]
{
get
{
return _ary[index];
}
set
{
_ary[index] = value;
}
}
public IEnumerator<ZqObject> GetEnumerator()
{
return ((IEnumerable<ZqObject>)_ary).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _ary.GetEnumerator();
}
}

View File

@ -0,0 +1,18 @@
using System;
using Mocha.Core;
namespace Mocha.Zq;
public class ZqAttribute : ZqObject
{
public class ZqAttributeCollection
: System.Collections.ObjectModel.Collection<ZqAttribute>
{
}
public string Name { get; set; }
public InstanceKey InstanceKey { get; set; }
public string DataType { get; set; }
}

View File

@ -0,0 +1,34 @@
using System;
using System.Text;
using Mocha.Core;
namespace Mocha.Zq;
public class ZqClass : ZqObject
{
public string Name { get; set; }
public InstanceKey InstanceKey { get; set; } = InstanceKey.Empty;
public ZqAccessModifier AccessModifier { get; set; } = ZqAccessModifier.None;
public ZqAttribute.ZqAttributeCollection Attributes { get; } = new ZqAttribute.ZqAttributeCollection();
public ZqMethod.ZqMethodCollection Functions { get; } = new ZqMethod.ZqMethodCollection();
public ZqInstance.ZqInstanceCollection Instances { get; } = new ZqInstance.ZqInstanceCollection();
public ZqRelationship.ZqRelationshipCollection Relationships { get; } = new ZqRelationship.ZqRelationshipCollection();
public ZqClass(string name)
{
Name = name;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(Name);
if (InstanceKey != InstanceKey.Empty)
{
sb.Append(", ");
sb.Append(InstanceKey.ToString());
}
return sb.ToString();
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace Mocha.Zq;
internal struct ZqDefParms
{
public ZqAccessModifier accessModifier;
public bool isStatic;
public bool isPublished;
public bool isStub;
}

View File

@ -0,0 +1,24 @@
using System;
namespace Mocha.Zq;
public class ZqCondition
{
public class ZqConditionCollection
: System.Collections.ObjectModel.Collection<ZqCondition>
{
}
public string Variable { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
public ZqCondition(string variable, string op, string value)
{
Variable = variable;
Operator = op;
Value = value;
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace Mocha.Zq;
public class ZqContext
{
public Dictionary<string, object> Variables { get; } = new Dictionary<string, object>();
}

View File

@ -0,0 +1,66 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace Mocha.Zq;
public struct ZqDataType
{
public static ZqDataType None { get; } = new ZqDataType("(none)", false);
public static ZqDataType Text { get; } = new ZqDataType("text", false);
public static ZqDataType Integer { get; } = new ZqDataType("integer", false);
public static ZqDataType Relationship { get; } = new ZqDataType("Relationship", false);
public string Name { get; }
public bool IsArray { get; }
private static readonly string[] attributeTypeNames = new string[]
{
"text", "boolean", "integer", "date"
};
public bool IsAttribute
{
get
{
return attributeTypeNames.Contains(Name);
}
}
public ZqDataType(string name, bool isArray)
{
Name = name;
IsArray = isArray;
}
public static ZqDataType Parse(string value)
{
string name = value;
bool isArray = false;
if (value.EndsWith("*"))
{
name = value.Substring(0, value.Length - 1);
isArray = true;
}
return new ZqDataType(name, isArray);
}
public override string ToString()
{
string str = Name;
if (IsArray)
{
str += "*";
}
return str;
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
if (obj is ZqDataType zqd)
{
return this.Name.Equals(zqd.Name) && this.IsArray == zqd.IsArray;
}
return false;
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace Mocha.Zq;
public abstract class ZqExpression : ZqObject
{
}

View File

@ -0,0 +1,16 @@
using System;
using Mocha.Core;
namespace Mocha.Zq;
public class ZqInstance : ZqObject
{
public class ZqInstanceCollection
: System.Collections.ObjectModel.Collection<ZqInstance>
{
}
public string Name { get; set; }
public InstanceKey InstanceKey { get; set; }
}

View File

@ -0,0 +1,53 @@
using System;
namespace Mocha.Zq;
public abstract class ZqMethod : ZqObject, IZqMethod
{
public class ZqMethodCollection
: System.Collections.ObjectModel.Collection<IZqMethod>
{
private Dictionary<string, IZqMethod> _itemsByName = new Dictionary<string, IZqMethod>();
public IZqMethod? this[string name]
{
get
{
if (_itemsByName.ContainsKey(name))
{
return _itemsByName[name];
}
return null;
}
}
protected override void ClearItems()
{
base.ClearItems();
_itemsByName.Clear();
}
protected override void InsertItem(int index, IZqMethod item)
{
base.InsertItem(index, item);
_itemsByName[item.Name] = item;
}
protected override void RemoveItem(int index)
{
_itemsByName.Remove(this[index].Name);
base.RemoveItem(index);
}
}
public string Name { get; set; }
public ZqParameter.ZqParameterCollection Parameters { get; } = new ZqParameter.ZqParameterCollection();
public ZqMethodCall? Executable { get; internal set; } = null;
public virtual ZqDataType ReturnDataType { get; set; }
public ZqMethod(string name)
{
Name = name;
ReturnDataType = ZqDataType.None;
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace Mocha.Zq;
public class ZqMethodCall : ZqMethod
{
public ZqObject? Method { get; internal set; } = null;
public object[] ParmValues { get; }
public string Name { get; set; }
public ZqDataType ReturnDataType { get; set; }
public ZqMethodCall? Executable => throw new NotImplementedException();
public ZqMethodCall(ZqObject executesMethod, object[] parmValues = null) : base(null)
{
Method = executesMethod;
ParmValues = parmValues;
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace Mocha.Zq;
public class ZqMethodReference : ZqExpression, IZqMethod
{
public string[] FullyQualifiedClassNameParts { get; }
public string Name { get; set; }
public ZqDataType ReturnDataType { get; set; }
public ZqMethodCall? Executable { get { return null; }}
public ZqMethodReference(string className, string methodName)
{
FullyQualifiedClassNameParts = className.Split(new char[] { '.' });
Name = methodName;
}
}

View File

@ -0,0 +1,7 @@
using System;
namespace Mocha.Zq;
public class ZqObject
{
}

View File

@ -0,0 +1,7 @@
namespace Mocha.Zq;
public enum ZqOperation
{
None = 0x00,
CreateClass
}

View File

@ -0,0 +1,27 @@
using System;
namespace Mocha.Zq;
public class ZqParameter
{
public class ZqParameterCollection
: System.Collections.ObjectModel.Collection<ZqParameter>
{
}
public string Name { get; set; }
public ZqDataType DataType { get; set; }
public ZqParameter(string name, ZqDataType dataType)
{
Name = name;
DataType = dataType;
}
public override string ToString()
{
return String.Format("{0} : {1}", Name, DataType);
}
}

View File

@ -0,0 +1,934 @@
using System;
using System.Dynamic;
using System.Linq.Expressions;
using System.Net.Http.Headers;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using MBS.Core;
using Mocha.Core;
using Mocha.Zq.Expressions;
using Mocha.Zq.Methods;
namespace Mocha.Zq;
public class ZqParser
{
private char[] tokenTerminators = new char[] { ' ', '{', '\n', '\t', ',', ':', '(', ')' };
private bool IsTokenNameTerminator(char token)
{
return tokenTerminators.Contains(token);
}
private char[] tokenSignificants = new char[] { ',', ':', '(', ')', '{', '}' };
private bool IsSignificantTokenChar(char token)
{
return tokenSignificants.Contains(token);
}
private bool CheckComment(string text, ref int i)
{
if (i >= text.Length - 1)
{
return false;
}
char c1 = text[i];
char c2 = text[i + 1];
if (c1 == '/' && c2 == '/')
{
i += 2;
// handle single-line comments
// -- encountered "//"; read until next line --
while (true)
{
if (i >= text.Length) return false;
char c = text[i];
if (c == '\n')
break;
i++;
}
}
else if (c1 == '/' && c2 == '*')
{
i += 2;
// handle multi-line or inline comments
while (true)
{
if (i >= text.Length - 1)
return false;
char ac1 = text[i];
char ac2 = text[i + 1];
if (ac1 == '*' && ac2 == '/')
{
i += 3;
break;
}
i++;
}
}
return true;
}
private enum TokenType
{
None = 0,
Comment
}
private struct Token
{
public static readonly Token Empty = new Token(TokenType.None, null, null);
public TokenType TokenType { get; }
public string? StartingSequence { get; }
public string? EndingSequence { get; }
public Token(TokenType type, string? startingSequence, string? endingSequence)
{
TokenType = type;
StartingSequence = startingSequence;
EndingSequence = endingSequence;
}
}
private string StripComments(string text)
{
Token[] tokens = new Token[]
{
new Token(TokenType.Comment, "/*", "*/"),
new Token(TokenType.Comment, "//", "\n")
};
Token insideTok = Token.Empty;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.Length; i++)
{
bool _continue = false;
foreach (Token tok in tokens)
{
if (i < text.Length - tok.StartingSequence.Length)
{
if (text.Substring(i, tok.StartingSequence.Length).Equals(tok.StartingSequence))
{
insideTok = tok;
string? contents = ReadUntil(text, ref i, tok.EndingSequence, false);
i--;
_continue = true;
break;
}
}
}
if (_continue)
continue;
sb.Append(text[i]);
}
return sb.ToString();
}
private string StripExtemporaneousWhitespace(string text)
{
StringBuilder sb = new StringBuilder();
bool hadWhitespace = false;
for (int i = 0; i < text.Length; i++)
{
if (i < text.Length - 1)
{
if (text[i] != '\n')
{
if (Char.IsWhiteSpace(text[i]) && Char.IsWhiteSpace(text[i + 1]))
{
hadWhitespace = true;
i++;
continue;
}
else if (Char.IsWhiteSpace(text[i]))
{
hadWhitespace = true;
continue;
}
}
}
if (hadWhitespace)
{
hadWhitespace = false;
sb.Append(' ');
}
sb.Append(text[i]);
}
return sb.ToString();
}
private Dictionary<string, string> BuildSections(string text)
{
Dictionary<string, string> sections = new Dictionary<string, string>();
string[] lines = text.Split(new char[] { '\n' });
string? nextLabel = null;
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Trim() == "")
continue;
if (lines[i].Trim().EndsWith(":") && !lines[i].Contains(" "))
{
nextLabel = lines[i].Substring(0, lines[i].Length - 1);
}
else
{
if (nextLabel != null)
{
nextLabel = nextLabel.Trim();
if (!sections.ContainsKey(nextLabel))
{
sections[nextLabel] = "";
}
sections[nextLabel] += lines[i].Trim() + '\n';
}
}
}
Dictionary<string, string> sections2 = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> sect in sections)
{
sections2[sect.Key] = StripExtemporaneousWhitespace(sections[sect.Key]);
}
return sections2;
}
public ZqObject? Parse(string text)
{
text = StripComments(text);
ZqClass? thisClass = null;
ZqDefParms parms = new ZqDefParms();
int i = 0;
string currentLabel = "";
while (true)
{
if (!CheckComment(text, ref i))
break;
/*
if (!SkipWhitespace(text, ref i))
{
break;
}
*/
string tok = ReadUntil(text, ref i, tokenTerminators, false);
if (!IsModifier(tok, ref parms))
{
if (tok.Equals("class"))
{
if (!CheckComment(text, ref i))
break;
ParseClass(text, ref i, ref thisClass, ref parms);
}
else if (tok.Equals("function"))
{
return ParseFunction(text, ref i, ref parms);
}
else if (tok.Equals("}"))
{
return thisClass;
}
}
}
return thisClass;
}
private ZqObject? ParseFunction2(string text, ref int i, ref ZqDefParms parms)
{
throw new NotImplementedException();
}
private bool IsModifier(string? tok, ref ZqDefParms parms)
{
if (tok == "published")
{
parms.isPublished = true;
return true;
}
else if (tok == "stub")
{
parms.isStub = true;
return true;
}
else if (tok == "static")
{
parms.isStatic = true;
return true;
}
else if (tok == "public")
{
parms.accessModifier = ZqAccessModifier.Public;
}
return false;
}
private void ParseClass(string text, ref int i, ref ZqClass thisClass, ref ZqDefParms parms)
{
string name = ReadUntil(text, ref i, '{', false).Trim();
i--;
InstanceKey ik = InstanceKey.Empty;
if (name.Contains(","))
{
string[] nameSplit = name.Split(new char[] { ',' }, 2);
name = nameSplit[0].Trim();
string strInstanceKey = nameSplit[1].Trim();
ik = InstanceKey.Parse(strInstanceKey);
}
thisClass = new ZqClass(name);
if (ik != InstanceKey.Empty)
{
thisClass.InstanceKey = ik;
}
knownClasses.Add(name, thisClass);
string body = ReadBetween(text, ref i, '{', '}');
Dictionary<string, string> sections = BuildSections(body);
if (sections.ContainsKey("attributes"))
{
string pp = sections["attributes"];
StringBuilder sb = new StringBuilder();
string? instanceName = null;
string? instanceKey = null;
string? dataType = null;
for (int j = 0; j < pp.Length; j++)
{
if (pp[j] == ',')
{
instanceName = sb.ToString();
sb.Clear();
}
else if (pp[j] == ':')
{
instanceKey = sb.ToString();
sb.Clear();
}
else if (pp[j] == '\n')
{
if (instanceName != null)
{
if (sb.Length > 0)
{
dataType = sb.ToString();
sb.Clear();
}
}
if (instanceName != null && instanceKey != null && dataType != null)
{
ZqAttribute inst = new ZqAttribute();
inst.Name = instanceName.Trim();
inst.InstanceKey = InstanceKey.Parse(instanceKey.Trim());
inst.DataType = dataType.Trim();
thisClass.Attributes.Add(inst);
instanceName = null;
instanceKey = null;
dataType = null;
}
}
else
{
sb.Append(pp[j]);
}
}
}
if (sections.ContainsKey("instances"))
{
string pp = sections["instances"];
StringBuilder sb = new StringBuilder();
string? instanceName = null;
string? instanceKey = null;
for (int j = 0; j < pp.Length; j++)
{
if (pp[j] == ',')
{
instanceName = sb.ToString();
sb.Clear();
}
else if (pp[j] == '\n')
{
if (instanceName != null)
{
if (sb.Length > 0)
{
instanceKey = sb.ToString();
sb.Clear();
}
}
if (instanceName != null && instanceKey != null)
{
ZqInstance inst = new ZqInstance();
inst.Name = instanceName;
inst.InstanceKey = InstanceKey.Parse(instanceKey);
thisClass.Instances.Add(inst);
instanceName = null;
instanceKey = null;
}
}
else
{
sb.Append(pp[j]);
}
}
}
if (sections.ContainsKey("relationships"))
{
string pp = sections["relationships"];
string[] lines = pp.Split(new char[] { '\n' });
foreach (string line in lines)
{
int j = 0;
if (line.Contains(","))
{
string relName = ReadUntil(line, ref j, ',', false);
if (line.Contains("->"))
{
string relKey = ReadUntil(line, ref j, "->", false).Trim();
int k = line.LastIndexOf(' ');
string relationshipTypeName = line.Substring(j, k - j).Trim();
string dataType = line.Substring(k).Trim();
thisClass.Relationships.Add(new ZqRelationship(relName, relationshipTypeName, ZqDataType.Parse(dataType), InstanceKey.Parse(relKey)));
}
}
}
}
if (sections.ContainsKey("functions"))
{
string pp = sections["functions"];
int j = 0;
while (j < pp.Length)
{
string tok2 = ReadUntil(pp, ref j, ' ', false);
if (!IsModifier(tok2, ref parms))
{
if (tok2 == "function")
{
IZqMethod? m = ParseFunction(pp, ref j, ref parms);
if (m != null)
{
thisClass.Functions.Add(m);
}
}
}
}
}
}
private ZqMethod? ParseFunction(string pp, ref int j, ref ZqDefParms defparms)
{
string functionName = ReadUntil(pp, ref j, '(', false).Trim();
List<ZqParameter> parmListList = new List<ZqParameter>();
string parmlist = ReadUntil(pp, ref j, ')', false);
if (parmlist.Length > 0)
{
string[] parms = parmlist.Split(new char[] { ',' });
foreach (string parm in parms)
{
string[] parmstr = parm.Split(new char[] { ':' });
string parmName = parmstr[0].Trim();
string dataType = parmstr[1].Trim();
parmListList.Add(new ZqParameter(parmName, ZqDataType.Parse(dataType)));
}
}
int old_j = j;
string next = ReadUntil(pp, ref j, new char[] { '{', '\n' }).Trim();
int iEquals = next.IndexOf('=');
string nextAfterEq = "";
if (iEquals > -1)
{
nextAfterEq = next.Substring(iEquals + 1).Trim();
}
string funcBody = "";
if ((String.IsNullOrEmpty(nextAfterEq) && pp.Contains("{")) || next.EndsWith("{"))
{
funcBody = ReadUntil(pp, ref j, new char[] { '}' }, false).Trim();
}
if (funcBody.StartsWith("{"))
{
funcBody = funcBody.Substring(1).Trim();
}
string returnDataType = "";
int iColon = next.IndexOf(':');
if (iColon > -1)
{
if (iEquals == -1)
{
returnDataType = next.Substring(iColon + 1).Trim();
if (defparms.isStub)
{
ZqStubMethod func = new ZqStubMethod(functionName, parmListList.ToArray(), ZqDataType.Parse(returnDataType));
j -= funcBody.Length;
return func;
}
else
{
}
}
else
{
returnDataType = next.Substring(iColon + 1, iEquals - iColon - 1).Trim();
ZqDataType dataType = ZqDataType.Parse(returnDataType);
string value = next.Substring(iEquals + 1).Trim();
/*
if (String.IsNullOrEmpty(value))
{
j = old_j;
next = ReadUntil(pp, ref j, new char[] { '{' }).Trim();
continue;
}
*/
// if (String.IsNullOrEmpty(funcBody) && !String.IsNullOrEmpty(value))
if (!String.IsNullOrEmpty(value) && value != "{")
{
object val = ParseValue(value);
ZqMethod func = new ZqSimpleReturnMethod(functionName, val);
func.ReturnDataType = ZqDataType.Parse(returnDataType);
return func;
}
else if (!funcBody.Contains("\n"))
{
if (!String.IsNullOrEmpty(funcBody))
{
value = funcBody;
}
object? val = ParseValue(value);
if (val is string)
{
return new ZqBuildAttributeMethod(functionName, val);
}
else if (val is ZqObject)
{
ZqMethod func = new ZqSimpleReturnMethod(functionName, (ZqObject)val);
func.ReturnDataType = ZqDataType.Parse(returnDataType);
return func;
}
}
else
{
/*
if (!SkipWhitespace(text, ref i))
{
break;
}
*/
ZqContext context = new ZqContext();
int k = 0;
Queue<ZqObject> exprs = new Queue<ZqObject>();
ZqObject? expr = null;
while (k < funcBody.Length)
{
expr = ParseExpression(funcBody, ref k, context);
if (expr is IZqMethod mb)
{
((IZqMethod)expr).Name = functionName;
((IZqMethod)expr).ReturnDataType = ZqDataType.Parse(returnDataType);
return (ZqMethod)expr;
}
else if (expr == null)
{
funcBody += " ";
}
else
{
exprs.Enqueue(expr);
}
}
while (exprs.Count > 0)
{
ZqObject expr1 = exprs.Dequeue();
if (expr1 is ZqVariableAssignment assn)
{
context.Variables[assn.VariableName] = assn.VariableValue;
}
else if (expr1 is ZqVariableReference varr)
{
if (exprs.Count == 0)
{
/*
switch (context.Variables[varr.Name].DataType)
{
case ZqDataType.Relationship:
{
// this is a GR, Get Relationship Method
thisClass.Functions.Add(new ZqGetRelationshipMethod(functionName, context.Variables[varr.Name]));
break;
}
case ZqDataType.Text:
case ZqDataType.Boolean:
{
// this is a BA, Build Attribute Method
thisClass.Functions.Add(new ZqBuildAttributeMethod(functionName, context.Variables[varr.Name]));
break;
}
}
*/
object rv = null;
if (context.Variables.ContainsKey(varr.Name))
{
return new ZqBuildAttributeMethod(functionName, context.Variables[varr.Name]);
}
else
{
/*
if (varr.ObjectName == "this")
{
if (thisClass.Relationships.Contains(varr.PropertyName))
{
thisClass.Functions.Add(new ZqGetRelationshipMethod(functionName, thisClass.Relationships[varr.PropertyName]));
}
}
*/
}
}
}
}
}
}
}
return null;
}
private object? ParseValue(string value)
{
if (value.Contains(",") || (!value.Contains(" ") && !value.Contains("{")))
{
// specify value
string[] values;
if (value.Contains(','))
{
values = value.Split(new char[] { ',' });
}
else
{
values = new string[] { value };
}
ZqObject val;
if (values.Length == 1)
{
if (values[0].Contains('(') && values[0].Contains(')'))
{
// is function call
string fullyQualifiedName = values[0].Substring(0, values[0].IndexOf('('));
string parmList = values[0].Substring(values[0].IndexOf('(') + 1, values[0].IndexOf(')') - values[0].IndexOf('(') - 1);
val = new ZqMethodCall(new ZqVariableReference(fullyQualifiedName), parmList.Split(new char[] { ',' }));
}
else
{
val = new ZqVariableReference(values[0].Trim());
}
}
else
{
val = new ZqArray(values.Length);
for (int k = 0; k < values.Length; k++)
{
((ZqArray)val)[k] = new ZqVariableReference(values[k].Trim());
}
}
return val;
}
else if (value.StartsWith("\"") && value.EndsWith("\""))
{
return value.Substring(1, value.Length - 2);
}
return null;
}
private string ReadBetween(string text, ref int i, char beginChar, char endChar)
{
StringBuilder sb = new StringBuilder();
int k = 0;
while (i < text.Length)
{
if (text[i] == beginChar)
{
if (k > 0)
{
sb.Append(text[i]);
}
k++;
i++;
}
else if (text[i] == endChar)
{
k--;
if (k > 0)
{
sb.Append(text[i]);
}
i++;
if (k == 0)
{
break;
}
}
else
{
sb.Append(text[i]);
i++;
}
}
return sb.ToString();
}
private Dictionary<string, ZqClass> knownClasses = new Dictionary<string, ZqClass>();
private ZqObject? ParseExpression(string funcBody, ref int j, ZqContext context)
{
string next = null;
ZqObject? expr = null;
char[] whitespace = new char[] { ' ', '\n', '\t' };
string firstToken = ReadUntil(funcBody, ref j, new char[] { ' ', '\n' }, false);
if (firstToken.Equals("if"))
{
expr = new ZqConditionalSelectAttributeMethod();
// SkipWhitespace(funcBody, ref j);
string varr = ReadUntil(funcBody, ref j, whitespace, false);
// SkipWhitespace(funcBody, ref j);
string op = ReadUntil(funcBody, ref j, whitespace, false);
// SkipWhitespace(funcBody, ref j);
string val = ReadUntil(funcBody, ref j, whitespace, false);
// SkipWhitespace(funcBody, ref j);
string _then = ReadUntil(funcBody, ref j, whitespace, false);
if (_then != "then")
{
return null;
}
// SkipWhitespace(funcBody, ref j);
string strExpr2 = ReadUntil(funcBody, ref j, whitespace, false);
int l = 0;
ZqObject? expr2 = ParseExpression(strExpr2, ref l, context);
// SkipWhitespace(funcBody, ref j);
string _else = ReadUntil(funcBody, ref j, whitespace, false);
if (_else != "else")
{
throw new ZqParserException();
}
// SkipWhitespace(funcBody, ref j);
string strExpr3 = ReadUntil(funcBody, ref j, '\n', false);
l = 0;
ZqObject? expr3 = ParseExpression(strExpr3, ref l, context);
((ZqConditionalSelectAttributeMethod)expr).Cases.Add(new ZqConditionalSelectAttributeCase
(
// true conditions
new ZqCondition[]
{
new ZqCondition(varr, op, val)
},
new ZqCondition[0], // false conditions,
true, // use any condition
expr2 // return value
));
((ZqConditionalSelectAttributeMethod)expr).Cases.Add(new ZqConditionalSelectAttributeCase
(
new ZqCondition[0], // true conditions,
new ZqCondition[]
{
// false conditions
new ZqCondition(varr, op, val)
},
true, // use any condition
expr3 // return value
));
return expr;
}
else if (firstToken.Equals("let"))
{
string varName = ReadUntil(funcBody, ref j, '=', false).Trim();
string varValue = ReadUntil(funcBody, ref j, '\n', false).Trim();
if (Decimal.TryParse(varValue, out decimal mValue))
{
context.Variables[varName] = mValue;
return new ZqVariableAssignment(varName, mValue);
}
context.Variables[varName] = varValue;
return new ZqVariableAssignment(varName, varValue);
}
else if (firstToken.Contains("(") && firstToken.EndsWith(")"))
{
// method call?
j = 0;
string fullyQualifiedName = ReadUntil(funcBody, ref j, '(', false);
string actualParameterList = ReadUntil(funcBody, ref j, ')', false);
string[] nameParts = fullyQualifiedName.Split(new char[] { '.' });
string[] parmValues = actualParameterList.Split(new char[] { ',' });
// if (knownClasses.ContainsKey(nameParts[0]))
// {
// ZqMethod func = knownClasses[nameParts[0]].Functions[nameParts[nameParts.Length - 1]];
string className = fullyQualifiedName.Substring(0, fullyQualifiedName.LastIndexOf('.'));
string methodName = fullyQualifiedName.Substring(fullyQualifiedName.LastIndexOf('.') + 1);
return new ZqMethodCall(new ZqMethodReference(className, methodName), parmValues);
// }
// return null;
}
else
{
// is variable?
return new ZqVariableReference(firstToken);
}
return expr;
}
private bool IsReturnAttributeDataType(string returnDataType)
{
return returnDataType.Equals("text") || returnDataType.Equals("numeric") || returnDataType.Equals("integer") || returnDataType.Equals("boolean");
}
/*
private bool SkipWhitespace(string text, ref int i)
{
while (i < text.Length - 1 && Char.IsWhiteSpace(text[i]) && Char.IsWhiteSpace(text[i + 1]))
{
i++;
}
if (i >= text.Length)
{
return false;
}
if (Char.IsWhiteSpace(text[i]))
{
i++;
}
if (i < text.Length)
{
return true;
}
return false;
}
*/
public ZqObject? Parse(Stream stream)
{
StreamReader reader = new StreamReader(stream);
string value = reader.ReadToEnd();
return Parse(value);
}
private string? ReadUntil(string text, ref int i, char v, bool includeLastChar = true)
{
return ReadUntil(text, ref i, new string[] { v.ToString() }, out char lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, char v, out char lastChar, bool includeLastChar = true)
{
return ReadUntil(text, ref i, new string[] { v.ToString() }, out lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, char[] vs, bool includeLastChar = true)
{
return ReadUntil(text, ref i, vs, out char c, includeLastChar);
}
private string? ReadUntil(string text, ref int i, char[] vs, out char lastChar, bool includeLastChar = true)
{
string[] svs = new string[vs.Length];
for (int k = 0; k < vs.Length; k++)
{
svs[k] = vs[k].ToString();
}
return ReadUntil(text, ref i, svs, out lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, string v, bool includeLastChar = true)
{
return ReadUntil(text, ref i, new string[] { v }, out char lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, string v, out char lastChar, bool includeLastChar = true)
{
return ReadUntil(text, ref i, new string[] { v }, out lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, string[] vs, bool includeLastChar = true)
{
return ReadUntil(text, ref i, vs, out char lastChar, includeLastChar);
}
private string? ReadUntil(string text, ref int i, string[] vs, out char lastChar, bool includeLastChar = true)
{
StringBuilder sb = new StringBuilder();
while (true)
{
if (i >= text.Length)
{
lastChar = '\0';
return sb.ToString();
}
bool _break = false;
foreach (string v in vs)
{
if (i + v.Length - 1 < text.Length && text.Substring(i, v.Length).Equals(v))
{
if (includeLastChar)
{
sb.Append(text.Substring(i, v.Length));
}
i += v.Length;
_break = true;
break;
}
}
if (_break)
break;
sb.Append(text[i]);
i++;
}
lastChar = text[i - 1];
return sb.ToString();
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace Mocha.Zq;
public class ZqParserException : Exception
{
}

View File

@ -0,0 +1,67 @@
using System;
using Mocha.Core;
namespace Mocha.Zq;
public class ZqRelationship : ZqExpression
{
public class ZqRelationshipCollection
: System.Collections.ObjectModel.Collection<ZqRelationship>
{
private Dictionary<string, ZqRelationship> _itemsByKey = new Dictionary<string, ZqRelationship>();
protected override void ClearItems()
{
base.ClearItems();
_itemsByKey.Clear();
}
protected override void InsertItem(int index, ZqRelationship item)
{
base.InsertItem(index, item);
_itemsByKey[item.Name] = item;
}
protected override void RemoveItem(int index)
{
_itemsByKey.Remove(this[index].Name);
base.RemoveItem(index);
}
public ZqRelationship? this[string name]
{
get
{
if (_itemsByKey.ContainsKey(name))
{
return _itemsByKey[name];
}
return null;
}
}
public bool Contains(string name)
{
return _itemsByKey.ContainsKey(name);
}
}
public string Name { get; }
public string RelationshipTypeName { get; }
public ZqDataType DataType { get; }
public InstanceKey InstanceKey { get; }
public ZqRelationship(string name, string relationshipTypeName, ZqDataType dataType, InstanceKey instanceKey)
{
Name = name;
RelationshipTypeName = relationshipTypeName;
DataType = dataType;
InstanceKey = instanceKey;
}
public override string ToString()
{
return String.Format("{0}, {1} -> {2} {3}", Name, InstanceKey, RelationshipTypeName);
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace Mocha.Zq;
public class ZqStubMethod : ZqMethod
{
public ZqStubMethod(string name, IEnumerable<ZqParameter> parms, ZqDataType returnDataType) : base(name)
{
if (parms != null)
{
foreach (ZqParameter parm in parms)
{
Parameters.Add(parm);
}
}
ReturnDataType = returnDataType;
}
}

View File

@ -0,0 +1,9 @@
namespace Mocha.Zq;
public enum ZqTokenType
{
None,
EndOfStream,
Separator,
Token
}

View File

@ -0,0 +1,16 @@
using System;
namespace Mocha.Zq;
public class ZqVariableAssignment : ZqExpression
{
public string VariableName { get; set; }
public object VariableValue { get; set; }
public ZqVariableAssignment(string variableName, object variableValue)
{
VariableName = variableName;
VariableValue = variableValue;
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Reflection;
namespace Mocha.Zq.Tests;
public class ClassDefinitionTests
{
[Test]
public void Class_with_Multiple_Attributes()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
attributes:
name, 4$1 : text
order, 4$7 : text
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Attributes.Count, Is.EqualTo(2));
Assert.That(((ZqClass)obj).Attributes[1].Name, Is.EqualTo("order"));
}
}

View File

@ -0,0 +1,34 @@
using Mocha.Core;
namespace Mocha.Zq.Tests;
public class CommentsTests
{
[Test]
public void SinglelineComment()
{
ZqParser zq = new ZqParser();
ZqObject? obj = zq.Parse(@"// class ZqTestClass2 { }");
// InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass2");
// Assert.That(c_ZqTestClass, Is.EqualTo(InstanceHandle.Empty));
Assert.That(obj, Is.Null);
}
[Test]
public void MultilineComment()
{
ZqParser zq = new ZqParser();
ZqObject? obj = zq.Parse(@"class /* ZqTestClass2 */ ZqTestClass3 { }");
// InstanceHandle c_ZqTestClass2 = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass2");
// Assert.That(c_ZqTestClass2, Is.EqualTo(InstanceHandle.Empty));
// InstanceHandle c_ZqTestClass3 = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass3");
// Assert.That(c_ZqTestClass3, Is.Not.EqualTo(InstanceHandle.Empty));
Assert.That(obj, Is.Not.Null);
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Name, Is.EqualTo("ZqTestClass3"));
}
}

View File

@ -0,0 +1 @@
global using NUnit.Framework;

View File

@ -0,0 +1,274 @@
using System;
using Mocha.Core;
using Mocha.Zq.Integration;
namespace Mocha.Zq.Tests;
public class IntegrationTests : Mocha.Core.Tests.OmsTestsBase
{
[Test]
public void Create_Class()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
zq.Evaluate(@"class ZqTestClass { }");
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
}
[Test]
public void UnitTestGCD()
{
Assert.Ignore();
/*
ZqIntegrator zq = new ZqIntegrator(Oms);
object? obj = zq.Evaluate(@"test GreatestCommonDivisorTests
{
case gcdTest {
assert GreatestCommonDivisor.gcd(16, 4) == 4 :: """"
assert GreatestCommonDivisor.gcd(4, 16) == 4 :: """"
assert GreatestCommonDivisor.gcd(15, 60) == 15 :: """"
assert GreatestCommonDivisor.gcd(15, 65) == 5 :: """"
assert GreatestCommonDivisor.gcd(1052, 52) == 4 :: """"
}
}");
Assert.That(obj, Is.TypeOf<ZqTest>());
ZqTest test = (ZqTest)obj;
Assert.That(test.Cases.Count, Is.EqualTo(1));
Assert.That(test.Cases[0].Assertions.Count, Is.EqualTo(5));
Assert.DoesNotThrow(delegate ()
{
ZqTestResult result = test.Run();
});
*/
}
[Test]
public void Create_Class_with_explicit_InstanceKey()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
InstanceKey ik = new InstanceKey(1, 411009);
zq.Evaluate("class ZqTestClass, " + ik.ToString() + " { }");
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
Assert.That(Oms.GetInstanceKey(c_ZqTestClass), Is.EqualTo(ik));
}
[Test]
public void Create_Class_with_Instances()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
zq.Evaluate(@"class ZqTestClass, 1$411009
{
instances:
TestInstance, 411009$1
AnotherTest, 411009$2
}");
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
IEnumerable<InstanceHandle> instances = Oms.GetInstancesOf(c_ZqTestClass);
Assert.That(instances.Count(), Is.EqualTo(2));
InstanceHandle i_1 = instances.First();
string name = Oms.GetAttributeValue<string>(i_1, Oms.GetInstance(KnownAttributeGuids.Text.Name));
Assert.That(name, Is.EqualTo("TestInstance"));
}
[Test]
public void Create_Get_Specific_Instances_Method_Singular()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject? obj = zq.Parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getInstance() : ZqTestClass = TestInstance
instances:
TestInstance, 411009$1
AnotherTest, 411009$2
}");
zq.Evaluate(obj);
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle TestInstance = Oms.GetInstancesOf(c_ZqTestClass).First();
Core.Oop.Method method = Oms.GetMethod(c_ZqTestClass, null, "getInstance", null, true);
Assert.That(method, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ih = Oms.Execute(context, method);
object? val = context.GetWorkData(ih);
Assert.That(val, Is.Not.Null);
Assert.That(((IEnumerable<InstanceHandle>)val).First(), Is.EqualTo(TestInstance));
}
[Test]
public void Create_Get_Specific_Instances_Method_Nonsingular()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject? obj = zq.Parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getInstance() : ZqTestClass* = TestInstance, AnotherTest
instances:
TestInstance, 411009$1
AnotherTest, 411009$2
}");
zq.Evaluate(obj);
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle[] insts = Oms.GetInstancesOf(c_ZqTestClass).ToArray();
Core.Oop.Method method = Oms.GetMethod(c_ZqTestClass, null, "getInstance", null, true);
Assert.That(method, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ih = Oms.Execute(context, method);
object? val = context.GetWorkData(ih);
Assert.That(val, Is.Not.Null);
Assert.That(((IEnumerable<InstanceHandle>)val).First(), Is.EqualTo(insts[0]));
Assert.That(((IEnumerable<InstanceHandle>)val).ElementAt(1), Is.EqualTo(insts[1]));
}
[Test]
public void Create_Multiple_Methods()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject? obj = zq.Parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getInstance() : ZqTestClass = TestInstance
static function getAnother() : ZqTestClass = AnotherTest
instances:
TestInstance, 411009$1
AnotherTest, 411009$2
}");
zq.Evaluate(obj);
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle TestInstance = Oms.GetInstancesOf(c_ZqTestClass).First();
Core.Oop.Method method = Oms.GetMethod(c_ZqTestClass, null, "getInstance", null, true);
Assert.That(method, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ih = Oms.Execute(context, method);
object? val = context.GetWorkData(ih);
Assert.That(val, Is.Not.Null);
Assert.That(((IEnumerable<InstanceHandle>)val).First(), Is.EqualTo(TestInstance));
}
[Test]
public void Create_Multiple_Different_Methods()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject? obj = zq.Parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getInstance() : ZqTestClass = TestInstance
static function gcd (p:integer, q : integer) : integer =
{
if q == 0
then p
else GreatestCommonDivisor.gcd(q, p % q)
}
static function getAnother() : ZqTestClass = AnotherTest
static function getAll() : ZqTestClass* = TestInstance, AnotherTest
instances:
TestInstance, 411009$1
AnotherTest, 411009$2
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(4));
zq.Evaluate(obj);
InstanceHandle c_ZqTestClass = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "ZqTestClass");
Assert.That(c_ZqTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle TestInstance = Oms.GetInstancesOf(c_ZqTestClass).First();
Core.Oop.Method method = Oms.GetMethod(c_ZqTestClass, null, "getInstance", null, true);
Assert.That(method, Is.Not.Null);
OmsContext context = Oms.CreateContext();
InstanceHandle ih = Oms.Execute(context, method);
object? val = context.GetWorkData(ih);
Assert.That(val, Is.Not.Null);
Assert.That(((IEnumerable<InstanceHandle>)val).First(), Is.EqualTo(TestInstance));
}
[Test]
public void Pull_Class_Definition_from_OMS()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject obj1 = zq.Import(Oms.GetInstance(KnownInstanceGuids.Classes.AccessModifier));
string code1 = zq.GenerateCode(obj1);
ZqObject obj2 = zq.Import(Oms.GetInstance(KnownInstanceGuids.Classes.Instance));
string code2 = zq.GenerateCode(obj2);
// ZqObject obj2 = zq.Parser.Parse(code);
// Assert.That(code, Is.EqualTo("function getParentClass() : Class* = this.forClass"));
}
[Test(Description = "Checks that a Get Relationship Method pulls from the OMS, converts to Zq, compiles, and converts back into Zq.")]
public void Pull_GR_Method_Definition_from_OMS()
{
ZqIntegrator zq = new ZqIntegrator(Oms);
ZqObject obj = zq.Import(Oms.GetInstance(KnownInstanceGuids.Methods.GetRelationship.Instance__get__Parent_Class));
string code = zq.GenerateCode(obj);
Assert.That(code, Is.EqualTo("function getParentClass() : Class* = this.forClass"));
ZqObject obj2 = zq.Parser.Parse(code);
string code2 = zq.GenerateCode(obj2);
Assert.That(code2, Is.EqualTo(code));
}
}

View File

@ -0,0 +1,88 @@
using System;
using Mocha.Zq.Methods;
namespace Mocha.Zq.Tests;
public class MathTests
{
[Test]
public void Greatest_Common_Divisor()
{
ZqParser zq = new ZqParser();
ZqObject? obj = zq.Parse(@" class GreatestCommonDivisor {
functions:
static function gcd (p:integer, q : integer) : integer = {
if q == 0
then p
else GreatestCommonDivisor.gcd(q, p % q)
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
if (obj is ZqClass zql)
{
Assert.That(zql.Name, Is.EqualTo("GreatestCommonDivisor"));
Assert.That(zql.Functions.Count, Is.EqualTo(1));
Assert.That(zql.Functions[0].Name, Is.EqualTo("gcd"));
Assert.That(zql.Functions[0], Is.TypeOf<ZqConditionalSelectAttributeMethod>());
/*
InstanceHandle c_GCD = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "GreatestCommonDivisor");
Assert.That(c_GCD, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle i_GcdMethod = zq.GetMethod("GreatestCommonDivisor.gcd");
Assert.That(i_GcdMethod, Is.Not.EqualTo(InstanceHandle.Empty));
*/
}
}
[Test]
public void Greatest_Common_Divisor_with_multiline_comment_in_the_middle_of_an_Expression()
{
ZqParser zq = new ZqParser();
ZqObject? obj = zq.Parse(@" class GreatestCommonDivisor {
functions:
static function gcd (p:integer, q : integer) : integer = {
if q == 0/* hey I'ma
multiline comment*/
then p
else GreatestCommonDivisor.gcd(q, p % q)
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
if (obj is ZqClass zql)
{
Assert.That(zql.Name, Is.EqualTo("GreatestCommonDivisor"));
Assert.That(zql.Functions.Count, Is.EqualTo(1));
Assert.That(zql.Functions[0].Name, Is.EqualTo("gcd"));
Assert.That(zql.Functions[0], Is.TypeOf<ZqConditionalSelectAttributeMethod>());
/*
InstanceHandle c_GCD = Oms.GetInstanceByName(Oms.GetInstance(KnownInstanceGuids.Classes.Class), "GreatestCommonDivisor");
Assert.That(c_GCD, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle i_GcdMethod = zq.GetMethod("GreatestCommonDivisor.gcd");
Assert.That(i_GcdMethod, Is.Not.EqualTo(InstanceHandle.Empty));
*/
}
}
}

View File

@ -0,0 +1,155 @@
using System;
using Mocha.Core;
using Mocha.Zq.Methods;
using NUnit.Framework.Interfaces;
namespace Mocha.Zq.Tests;
public class MethodDefinitionTests
{
[Test]
public void Stub_Function_Call_Test()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class CommonInstanceSet, 1$770
{
functions:
// the actual method definition is in the MADI OMS
// we re-declare the function here only to use it within Zq
static stub function instanceByInstanceID(instanceID : text) : instance
static function testStubFunctionCall() : Class = {
CommonInstanceSet.instanceByInstanceID('1$770')
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(2));
Assert.That(((ZqClass)obj).Functions[1], Is.TypeOf<ZqSimpleReturnMethod>());
Assert.That(((ZqSimpleReturnMethod)((ZqClass)obj).Functions[1]).ReturnValue, Is.TypeOf<ZqMethodCall>());
Assert.That(((ZqMethodCall)((ZqSimpleReturnMethod)((ZqClass)obj).Functions[1]).ReturnValue).ParmValues.Length, Is.EqualTo(1));
// FIXME: the text literal, once parsed, should not have '' / "" quotes
Assert.That(((ZqMethodCall)((ZqSimpleReturnMethod)((ZqClass)obj).Functions[1]).ReturnValue).ParmValues[0], Is.EqualTo("'1$770'"));
}
[Test]
public void Stub_Function_Test()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
// the actual method definition is in the MADI OMS
// we re-declare the function here only to use it within Zq
static stub function testStub() : integer
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(1));
Assert.That(((ZqClass)obj).Functions[0], Is.TypeOf<ZqStubMethod>());
Assert.That(((ZqMethod)((ZqClass)obj).Functions[0]).ReturnDataType, Is.EqualTo(ZqDataType.Integer));
}
[Test]
public void BA_String_Inline_Test()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getAString() : text = ""Build Attribute Method""
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(1));
Assert.That(((ZqClass)obj).Functions[0], Is.TypeOf<ZqBuildAttributeMethod>());
Assert.That(((ZqBuildAttributeMethod)((ZqClass)obj).Functions[0]).InitialValue, Is.EqualTo("Build Attribute Method"));
}
[Test]
public void BA_String_Fullbody_Test()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getAString() : text = {
""Build Attribute Method""
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(1));
Assert.That(((ZqClass)obj).Functions[0], Is.TypeOf<ZqBuildAttributeMethod>());
Assert.That(((ZqBuildAttributeMethod)((ZqClass)obj).Functions[0]).InitialValue, Is.EqualTo("Build Attribute Method"));
}
[Test]
public void Temporary_Variable_Test()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
functions:
static function getSomeInteger() : integer =
{
let someInteger = 5
someInteger
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Functions.Count, Is.EqualTo(1));
Assert.That(((ZqClass)obj).Functions[0], Is.TypeOf<ZqBuildAttributeMethod>());
Assert.That(((ZqBuildAttributeMethod)((ZqClass)obj).Functions[0]).InitialValue, Is.EqualTo(5));
}
[Test]
public void Get_Relationship_Method()
{
ZqParser parser = new ZqParser();
ZqObject? obj = parser.Parse(@"class ZqTestClass, 1$411009
{
attributes:
name, 4$1 : text
order, 4$7 : text
relationships:
hasAnotherTestClass, 3$410001 -> has another ZqTestClass*
functions:
public function getAnotherZqTestClass() : ZqTestClass = {
this.hasAnotherTestClass
}
}");
Assert.That(obj, Is.TypeOf<ZqClass>());
Assert.That(((ZqClass)obj).Relationships.Count, Is.EqualTo(1));
Assert.That(((ZqClass)obj).Relationships[0].Name, Is.EqualTo("hasAnotherTestClass"));
Assert.That(((ZqClass)obj).Relationships[0].InstanceKey, Is.EqualTo(new InstanceKey(3, 410001)));
Assert.That(((ZqClass)obj).Relationships[0].DataType, Is.EqualTo(new ZqDataType("ZqTestClass", true)));
}
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
<ProjectReference Include="../../src/lib/Mocha.Core/Mocha.Core.csproj" />
<ProjectReference Include="../../src/lib/Mocha.Zq.Integration/Mocha.Zq.Integration.csproj" />
<ProjectReference Include="../../src/lib/Mocha.Zq/Mocha.Zq.csproj" />
<ProjectReference Include="../Mocha.Core.Tests/Mocha.Core.Tests.csproj" />
</ItemGroup>
</Project>