Skip to content

Commit

Permalink
Redesigned lambdas and projections handling
Browse files Browse the repository at this point in the history
Resolves #5
  • Loading branch information
maciejlach committed Oct 1, 2014
1 parent 6be5d4a commit a714890
Show file tree
Hide file tree
Showing 12 changed files with 372 additions and 70 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
------------------------------------------------------------------------------
qSharp 2.0.7 [TBA]
qSharp 2.1.0 [2014.10.01]
------------------------------------------------------------------------------

- Fix: validate lambda expression upon construction
- Redesigned lambdas and projections handling

------------------------------------------------------------------------------
qSharp 2.0.6 [2014.09.11]
Expand Down
3 changes: 3 additions & 0 deletions qSharp/qSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="src\QProjection.cs" />
<Compile Include="src\QFunction.cs" />
<Compile Include="src\QBasicConnection.cs" />
<Compile Include="src\QCallbackConnection.cs" />
<Compile Include="src\QMessage.cs" />
Expand Down Expand Up @@ -98,6 +100,7 @@
<None Include="test\QCompressedExpressions.out" />
<None Include="test\QExpressions.3.out" />
<None Include="test\QExpressions.out" />
<None Include="test\QExpressionsFunctions.out" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
65 changes: 65 additions & 0 deletions qSharp/src/QFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright (c) 2011-2014 Exxeleron GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

using System;

namespace qSharp
{
/// <summary>
/// Represents q function.
///
/// Note that the QFunction instances cannot be serialized to IPC protocol.
/// </summary>
public class QFunction
{
private readonly byte qTypeCode;

/// <summary>
/// Creates representation of q function with given q type code.
/// </summary>
protected QFunction(byte qTypeCode)
{
this.qTypeCode = qTypeCode;
}

/// <summary>
/// Retrieve q type code connected with function.
/// </summary>
public byte QTypeCode
{
get { return qTypeCode; }
}


/// <summary>
/// Returns a System.String that represents the current QFunction.
/// </summary>
/// <returns>A System.String that represents the current QFunction</returns>
public override string ToString()
{
return "QFunction#" + qTypeCode + "h";
}


/// <summary>
/// Creates representation of q function with given q type code.
/// </summary>
internal static QFunction Create(byte qTypeCode)
{
return new QFunction(qTypeCode);
}
}
}
34 changes: 14 additions & 20 deletions qSharp/src/QLambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,43 @@
//

using System;
using System.Text.RegularExpressions;

namespace qSharp
{
/// <summary>
/// Represents a q lambda expression.
/// </summary>
public sealed class QLambda
public sealed class QLambda : QFunction
{
private const string LambdaRegex = @"\s*(k\))?\s*\{.*\}";

private readonly string expression;
private readonly Array parameters;

/// <summary>
/// Creates new QLambda instance with given body and parameters.
/// Note that expression is trimmed and required to be enclosed in { and } brackets.
/// Creates new QLambda instance with given body. Note that expression is trimmed and required to be enclosed
/// in { and } brackets.
/// </summary>
public QLambda(string expression, Array parameters = null)
public QLambda(string expression)
: base((byte)QType.Lambda)
{
if (expression == null)
{
throw new ArgumentException("Lambda expression cannot be null");
}
expression = expression.Trim();

if (expression.Length == 0)
{
throw new ArgumentException("Lambda expression cannot be empty");
}

if (expression[0] != '{' || expression[expression.Length - 1] != '}')
if (!Regex.IsMatch(expression, LambdaRegex, RegexOptions.Compiled))
{
throw new ArgumentException("Lambda expression is expected to be enclosed in {} brackets");
throw new ArgumentException("Invalid lambda expresion: " + expression);
}

this.expression = expression;
this.parameters = parameters;
}

/// <summary>
Expand All @@ -60,14 +62,6 @@ public string Expression
get { return expression; }
}

/// <summary>
/// Gets parameters of a q lambda expression.
/// </summary>
public Array Parameters
{
get { return parameters; }
}

/// <summary>
/// Determines whether the specified System.Object is equal to the current QLambda.
/// </summary>
Expand All @@ -86,7 +80,7 @@ public override bool Equals(Object obj)
return false;
}

return expression.Equals(l.expression) && Utils.ArrayEquals(parameters, l.parameters);
return expression.Equals(l.expression);
}

/// <summary>
Expand All @@ -101,7 +95,7 @@ public bool Equals(QLambda l)
return false;
}

return expression.Equals(l.expression) && Utils.ArrayEquals(parameters, l.parameters);
return expression.Equals(l.expression);
}

/// <summary>
Expand All @@ -119,7 +113,7 @@ public override int GetHashCode()
/// <returns>A System.String that represents the current QLambda</returns>
public override string ToString()
{
return "QLambda: " + expression + (parameters == null ? "" : Utils.ArrayToString(parameters));
return "QLambda: " + expression;
}
}
}
99 changes: 99 additions & 0 deletions qSharp/src/QProjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// Copyright (c) 2011-2014 Exxeleron GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

using System;

namespace qSharp
{
/// <summary>
/// Represents a q projection.
/// </summary>
public sealed class QProjection : QFunction
{
private readonly Array parameters;

/// <summary>
/// Creates new QProjection instance with given parameters.
/// </summary>
public QProjection(Array parameters)
: base((byte) QType.Projection)
{
this.parameters = parameters;
}

/// <summary>
/// Gets parameters of a q lambda expression.
/// </summary>
public Array Parameters
{
get { return parameters; }
}

/// <summary>
/// Determines whether the specified System.Object is equal to the current QProjection.
/// </summary>
/// <param name="obj">The System.Object to compare with the current QProjection.</param>
/// <returns>true if the specified System.Object is equal to the current QProjection; otherwise, false</returns>
public override bool Equals(Object obj)
{
if (obj == null)
{
return false;
}

var p = obj as QProjection;
if (p == null)
{
return false;
}

return Utils.ArrayEquals(parameters, p.parameters);
}

/// <summary>
/// Determines whether the specified QProjection is equal to the current QProjection.
/// </summary>
/// <param name="l">The QProjection to compare with the current QProjection.</param>
/// <returns>true if the specified QProjection is equal to the current QProjection; otherwise, false</returns>
public bool Equals(QProjection p)
{
if (p == null)
{
return false;
}

return Utils.ArrayEquals(parameters, p.parameters);
}

/// <summary>
/// Serves as a hash function for a QProjection type.
/// </summary>
/// <returns>A hash code for the current QProjection</returns>
public override int GetHashCode()
{
return parameters == null ? 0 : parameters.Length;
}

/// <summary>
/// Returns a System.String that represents the current QLambda.
/// </summary>
/// <returns>A System.String that represents the current QLambda</returns>
public override string ToString()
{
return "QProjection: " + (parameters == null ? "<null>" : Utils.ArrayToString(parameters));
}
}
}
82 changes: 56 additions & 26 deletions qSharp/src/QReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,21 @@ private object ReadObject()
return ReadList(qtype);
case QType.GeneralList:
return ReadGeneralList();
case QType.NullItem:
reader.ReadSByte(); // ignore
return null;
case QType.Error:
return ReadError();
case QType.Lambda:
return ReadLambda();
case QType.LambdaPart:
return ReadLambdaPart();
case QType.Projection:
case QType.UnaryPrimitiveFunc:
case QType.BinaryPrimitiveFunc:
case QType.TernaryOperatorFunc:
case QType.CompositionFunc:
case QType.AdverbFunc106:
case QType.AdverbFunc107:
case QType.AdverbFunc108:
case QType.AdverbFunc109:
case QType.AdverbFunc110:
case QType.AdverbFunc111:
return ReadFunction(qtype);
case QType.Dictionary:
return ReadDictionary();
case QType.Table:
Expand Down Expand Up @@ -497,29 +503,53 @@ private object ReadError()
throw new QException(ReadSymbol());
}

private QLambda ReadLambda()
private QFunction ReadFunction(QType qtype)
{
ReadSymbol();
var expression = (char[])ReadObject();
if (expression == null)
{
throw new QReaderException("Malformed lambda expression");
}
return new QLambda(new string(expression));
}

private QLambda ReadLambdaPart()
{
int length = reader.ReadInt32() - 1;
QLambda lambda = ReadLambda();
var parameters = new object[length];

for (int i = 0; i < length; i++)
switch (qtype)
{
parameters[i] = ReadObject();
case QType.Lambda:
{
reader.ReadSymbol(encoding); // ignore context
var expression = (char[])ReadObject();
return new QLambda(new string(expression));
}
case QType.Projection:
{
int length = reader.ReadInt32();
var parameters = new object[length];
for (int i = 0; i < length; i++)
{
parameters[i] = ReadObject();
}
return new QProjection(parameters);
}
case QType.UnaryPrimitiveFunc:
{
var code = reader.ReadByte();
return code == 0 ? null : QFunction.Create((byte)qtype);
}
case QType.BinaryPrimitiveFunc:
case QType.TernaryOperatorFunc:
{
var code = reader.ReadByte(); // ignore
return QFunction.Create((byte)qtype);
}
case QType.CompositionFunc:
{
int length = reader.ReadInt32();
var parameters = new object[length];
for (int i = 0; i < length; i++)
{
parameters[i] = ReadObject();
}
return QFunction.Create((byte)qtype);
}
default:
{
ReadObject(); // ignore
return QFunction.Create((byte)qtype);
}
}

return new QLambda(lambda.Expression, parameters);
}

private object ReadDictionary()
Expand Down
Loading

0 comments on commit a714890

Please sign in to comment.