preliminary implementation of Zq scripting language for MADI
This commit is contained in:
parent
9b501f29f6
commit
f1d5768b98
@ -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}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
291
mocha-dotnet/src/lib/Mocha.Zq.Integration/ZqIntegrator.cs
Normal file
291
mocha-dotnet/src/lib/Mocha.Zq.Integration/ZqIntegrator.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
13
mocha-dotnet/src/lib/Mocha.Zq/Expressions/ZqLiteral.cs
Normal file
13
mocha-dotnet/src/lib/Mocha.Zq/Expressions/ZqLiteral.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
10
mocha-dotnet/src/lib/Mocha.Zq/IZqMethod.cs
Normal file
10
mocha-dotnet/src/lib/Mocha.Zq/IZqMethod.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public interface IZqMethod
|
||||
{
|
||||
string Name { get; set; }
|
||||
ZqDataType ReturnDataType { get; set; }
|
||||
ZqMethodCall? Executable { get; }
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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();
|
||||
|
||||
}
|
||||
@ -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; }
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
14
mocha-dotnet/src/lib/Mocha.Zq/Mocha.Zq.csproj
Normal file
14
mocha-dotnet/src/lib/Mocha.Zq/Mocha.Zq.csproj
Normal 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>
|
||||
11
mocha-dotnet/src/lib/Mocha.Zq/ZqAccessModifier.cs
Normal file
11
mocha-dotnet/src/lib/Mocha.Zq/ZqAccessModifier.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public enum ZqAccessModifier
|
||||
{
|
||||
None,
|
||||
Public,
|
||||
Protected,
|
||||
Internal,
|
||||
ProtectedInternal,
|
||||
Private
|
||||
}
|
||||
37
mocha-dotnet/src/lib/Mocha.Zq/ZqArray.cs
Normal file
37
mocha-dotnet/src/lib/Mocha.Zq/ZqArray.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
18
mocha-dotnet/src/lib/Mocha.Zq/ZqAttribute.cs
Normal file
18
mocha-dotnet/src/lib/Mocha.Zq/ZqAttribute.cs
Normal 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; }
|
||||
|
||||
}
|
||||
34
mocha-dotnet/src/lib/Mocha.Zq/ZqClass.cs
Normal file
34
mocha-dotnet/src/lib/Mocha.Zq/ZqClass.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
12
mocha-dotnet/src/lib/Mocha.Zq/ZqClassDefinition.cs
Normal file
12
mocha-dotnet/src/lib/Mocha.Zq/ZqClassDefinition.cs
Normal 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;
|
||||
|
||||
}
|
||||
24
mocha-dotnet/src/lib/Mocha.Zq/ZqCondition.cs
Normal file
24
mocha-dotnet/src/lib/Mocha.Zq/ZqCondition.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
8
mocha-dotnet/src/lib/Mocha.Zq/ZqContext.cs
Normal file
8
mocha-dotnet/src/lib/Mocha.Zq/ZqContext.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public class ZqContext
|
||||
{
|
||||
public Dictionary<string, object> Variables { get; } = new Dictionary<string, object>();
|
||||
}
|
||||
66
mocha-dotnet/src/lib/Mocha.Zq/ZqDataType.cs
Normal file
66
mocha-dotnet/src/lib/Mocha.Zq/ZqDataType.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
8
mocha-dotnet/src/lib/Mocha.Zq/ZqExpression.cs
Normal file
8
mocha-dotnet/src/lib/Mocha.Zq/ZqExpression.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public abstract class ZqExpression : ZqObject
|
||||
{
|
||||
|
||||
}
|
||||
16
mocha-dotnet/src/lib/Mocha.Zq/ZqInstance.cs
Normal file
16
mocha-dotnet/src/lib/Mocha.Zq/ZqInstance.cs
Normal 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; }
|
||||
}
|
||||
53
mocha-dotnet/src/lib/Mocha.Zq/ZqMethod.cs
Normal file
53
mocha-dotnet/src/lib/Mocha.Zq/ZqMethod.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
20
mocha-dotnet/src/lib/Mocha.Zq/ZqMethodCall.cs
Normal file
20
mocha-dotnet/src/lib/Mocha.Zq/ZqMethodCall.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
18
mocha-dotnet/src/lib/Mocha.Zq/ZqMethodReference.cs
Normal file
18
mocha-dotnet/src/lib/Mocha.Zq/ZqMethodReference.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
7
mocha-dotnet/src/lib/Mocha.Zq/ZqObject.cs
Normal file
7
mocha-dotnet/src/lib/Mocha.Zq/ZqObject.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public class ZqObject
|
||||
{
|
||||
}
|
||||
7
mocha-dotnet/src/lib/Mocha.Zq/ZqOperation.cs
Normal file
7
mocha-dotnet/src/lib/Mocha.Zq/ZqOperation.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public enum ZqOperation
|
||||
{
|
||||
None = 0x00,
|
||||
CreateClass
|
||||
}
|
||||
27
mocha-dotnet/src/lib/Mocha.Zq/ZqParameter.cs
Normal file
27
mocha-dotnet/src/lib/Mocha.Zq/ZqParameter.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
934
mocha-dotnet/src/lib/Mocha.Zq/ZqParser.cs
Normal file
934
mocha-dotnet/src/lib/Mocha.Zq/ZqParser.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
8
mocha-dotnet/src/lib/Mocha.Zq/ZqParserException.cs
Normal file
8
mocha-dotnet/src/lib/Mocha.Zq/ZqParserException.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public class ZqParserException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
67
mocha-dotnet/src/lib/Mocha.Zq/ZqRelationship.cs
Normal file
67
mocha-dotnet/src/lib/Mocha.Zq/ZqRelationship.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
18
mocha-dotnet/src/lib/Mocha.Zq/ZqStubMethod.cs
Normal file
18
mocha-dotnet/src/lib/Mocha.Zq/ZqStubMethod.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
9
mocha-dotnet/src/lib/Mocha.Zq/ZqTokenType.cs
Normal file
9
mocha-dotnet/src/lib/Mocha.Zq/ZqTokenType.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Mocha.Zq;
|
||||
|
||||
public enum ZqTokenType
|
||||
{
|
||||
None,
|
||||
EndOfStream,
|
||||
Separator,
|
||||
Token
|
||||
}
|
||||
16
mocha-dotnet/src/lib/Mocha.Zq/ZqVariableAssignment.cs
Normal file
16
mocha-dotnet/src/lib/Mocha.Zq/ZqVariableAssignment.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
26
mocha-dotnet/tests/Mocha.Zq.Tests/ClassDefinitionTests.cs
Normal file
26
mocha-dotnet/tests/Mocha.Zq.Tests/ClassDefinitionTests.cs
Normal 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"));
|
||||
}
|
||||
|
||||
}
|
||||
34
mocha-dotnet/tests/Mocha.Zq.Tests/Comments.cs
Normal file
34
mocha-dotnet/tests/Mocha.Zq.Tests/Comments.cs
Normal 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"));
|
||||
}
|
||||
|
||||
}
|
||||
1
mocha-dotnet/tests/Mocha.Zq.Tests/GlobalUsings.cs
Normal file
1
mocha-dotnet/tests/Mocha.Zq.Tests/GlobalUsings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
||||
274
mocha-dotnet/tests/Mocha.Zq.Tests/IntegrationTests.cs
Normal file
274
mocha-dotnet/tests/Mocha.Zq.Tests/IntegrationTests.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
88
mocha-dotnet/tests/Mocha.Zq.Tests/MathTests.cs
Normal file
88
mocha-dotnet/tests/Mocha.Zq.Tests/MathTests.cs
Normal 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));
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
155
mocha-dotnet/tests/Mocha.Zq.Tests/MethodDefinitionTests.cs
Normal file
155
mocha-dotnet/tests/Mocha.Zq.Tests/MethodDefinitionTests.cs
Normal 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)));
|
||||
}
|
||||
|
||||
}
|
||||
28
mocha-dotnet/tests/Mocha.Zq.Tests/Mocha.Zq.Tests.csproj
Normal file
28
mocha-dotnet/tests/Mocha.Zq.Tests/Mocha.Zq.Tests.csproj
Normal 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>
|
||||
Loading…
x
Reference in New Issue
Block a user