Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

check array indices as a separate step (so it also runs for unityscri…

…pt);

extract most SlicingExpression handling out of ProcessMethodBodies;
  • Loading branch information...
commit 75796ae0befcee96fda8e5bc45e3fba9a3b57154 1 parent 3862e61
@bamboo authored
View
9 src/Boo.Lang.Compiler/Ast/AstNodePredicates.cs
@@ -6,7 +6,7 @@ public static class AstNodePredicates
{
public static bool IsComplexSlicing(this SlicingExpression node)
{
- return node.Indices.Any(AstUtil.IsComplexSlice);
+ return node.Indices.Any(IsComplexSlice);
}
public static bool IsTargetOfAssignment(this Expression node)
@@ -16,5 +16,12 @@ public static bool IsTargetOfAssignment(this Expression node)
return false;
return node == parentExpression.Left && AstUtil.IsAssignment(parentExpression);
}
+
+ public static bool IsComplexSlice(Slice slice)
+ {
+ return slice.End != null
+ || slice.Step != null
+ || slice.Begin == OmittedExpression.Default;
+ }
}
}
View
7 src/Boo.Lang.Compiler/Ast/AstUtil.cs
@@ -80,13 +80,6 @@ public static string GetMethodNameForOperator(UnaryOperatorType op)
return "op_" + op;
}
- public static bool IsComplexSlice(Slice slice)
- {
- return slice.End != null
- || slice.Step != null
- || slice.Begin == OmittedExpression.Default;
- }
-
public static Node GetMemberAnchor(Node node)
{
var member = node as MemberReferenceExpression;
View
4 src/Boo.Lang.Compiler/Boo.Lang.Compiler.csproj
@@ -447,6 +447,7 @@
<Compile Include="Steps\CheckMembersProtectionLevel.cs" />
<Compile Include="Steps\CheckMemberTypes.cs" />
<Compile Include="Steps\CheckNeverUsedMembers.cs" />
+ <Compile Include="Steps\CheckSlicingExpressions.cs" />
<Compile Include="Steps\ClosureSignatureInferrer.cs" />
<Compile Include="Steps\ConstantFolding.cs" />
<Compile Include="Steps\ContextAnnotations.cs" />
@@ -455,6 +456,7 @@
<Compile Include="Steps\EmitAssembly.cs" />
<Compile Include="Steps\EntityPredicates.cs" />
<Compile Include="Steps\ExpandAstLiterals.cs" />
+ <Compile Include="Steps\ExpandComplexSlicingExpressions.cs" />
<Compile Include="Steps\ExpandDuckTypedExpressions.cs" />
<Compile Include="Steps\ExpandPropertiesAndEvents.cs" />
<Compile Include="Steps\ExpandVarArgsMethodInvocations.cs" />
@@ -481,6 +483,7 @@
<Compile Include="Steps\MacroProcessing\NodeGeneratorExpander.cs" />
<Compile Include="Steps\MacroProcessing\TypeMemberStatementBubbler.cs" />
<Compile Include="Steps\MergePartialTypes.cs" />
+ <Compile Include="Steps\MethodTrackingVisitorCompilerStep.cs" />
<Compile Include="Steps\NormalizeExpressions.cs" />
<Compile Include="Steps\NormalizeIterationStatements.cs" />
<Compile Include="Steps\NormalizeStatementModifiers.cs" />
@@ -649,6 +652,7 @@
<Compile Include="TypeSystem\Services\MetadataUtil.cs" />
<Compile Include="TypeSystem\Services\NameResolutionService.cs" />
<Compile Include="TypeSystem\Services\RuntimeMethodCache.cs" />
+ <Compile Include="TypeSystem\Services\TypeChecker.cs" />
<Compile Include="TypeSystem\Services\TypeCompatibilityRules.cs" />
<Compile Include="TypeSystem\Services\TypeSystemServices.cs" />
<Compile Include="TypeSystem\TypeCollector.cs" />
View
9 src/Boo.Lang.Compiler/Pipelines/CheckForErrors.cs
@@ -26,16 +26,17 @@
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using Boo.Lang.Compiler.Steps;
+
namespace Boo.Lang.Compiler.Pipelines
{
- using Boo.Lang.Compiler.Steps;
-
public class CheckForErrors : ResolveExpressions
{
public CheckForErrors()
{
- this.BreakOnErrors = false;
- this.Add(new StricterErrorChecking());
+ BreakOnErrors = false;
+ Add(new CheckSlicingExpressions());
+ Add(new StricterErrorChecking());
}
}
}
View
5 src/Boo.Lang.Compiler/Pipelines/Compile.cs
@@ -47,12 +47,15 @@ public Compile()
Add(new VerifyExtensionMethods());
Add(new CheckIdentifiers());
+ Add(new CheckSlicingExpressions());
Add(new StricterErrorChecking());
Add(new DetectNotImplementedFeatureUsage());
Add(new CheckAttributesUsage());
-
+
Add(new ExpandDuckTypedExpressions());
+ Add(new ExpandComplexSlicingExpressions());
+
Add(new ProcessAssignmentsToValueTypeMembers());
Add(new ExpandPropertiesAndEvents());
View
69 src/Boo.Lang.Compiler/Steps/CheckSlicingExpressions.cs
@@ -0,0 +1,69 @@
+using Boo.Lang.Compiler.Ast;
+using Boo.Lang.Compiler.TypeSystem;
+using Boo.Lang.Compiler.TypeSystem.Services;
+using Boo.Lang.Environments;
+
+namespace Boo.Lang.Compiler.Steps
+{
+ public class CheckSlicingExpressions : AbstractFastVisitorCompilerStep
+ {
+ public override void OnSlicingExpression(SlicingExpression node)
+ {
+ base.OnSlicingExpression(node);
+
+ var arrayType = GetExpressionType(node.Target) as IArrayType;
+ if (arrayType == null)
+ return;
+
+ if (arrayType.Rank != node.Indices.Count)
+ Error(CompilerErrorFactory.InvalidArrayRank(node, node.Target.ToCodeString(), arrayType.Rank, node.Indices.Count));
+ }
+
+ public override void OnSlice(Slice node)
+ {
+ base.OnSlice(node);
+
+ if (TypeSystemServices.IsDuckTyped((Expression) node.ParentNode))
+ return;
+
+ AssertInt(node.Begin);
+ AssertOptionalInt(node.End);
+ if (node.Step != null)
+ CompilerErrorFactory.NotImplemented(node.Step, "slicing step");
+ }
+
+ private void AssertInt(Expression e)
+ {
+ AssertExpressionTypeIsCompatibleWith(TypeSystemServices.IntType, e);
+ }
+
+ private void AssertExpressionTypeIsCompatibleWith(IType expectedType, Expression e)
+ {
+ TypeChecker.AssertTypeCompatibility(e, expectedType, GetExpressionType(e));
+ }
+
+ private void AssertOptionalInt(Expression e)
+ {
+ if (IsNotOmitted(e))
+ AssertInt(e);
+ }
+
+ private static bool IsNotOmitted(Expression e)
+ {
+ return e != null && e != OmittedExpression.Default;
+ }
+
+ private TypeChecker TypeChecker
+ {
+ get { return _typeChecker.Instance; }
+ }
+
+ public override void Dispose()
+ {
+ _typeChecker = new EnvironmentProvision<TypeChecker>();
+ base.Dispose();
+ }
+
+ private EnvironmentProvision<TypeChecker> _typeChecker;
+ }
+}
View
193 src/Boo.Lang.Compiler/Steps/ExpandComplexSlicingExpressions.cs
@@ -0,0 +1,193 @@
+using System.Linq;
+using Boo.Lang.Compiler.Ast;
+using Boo.Lang.Compiler.TypeSystem;
+using Boo.Lang.Compiler.TypeSystem.Internal;
+using Boo.Lang.Compiler.TypeSystem.Services;
+using Boo.Lang.Environments;
+
+namespace Boo.Lang.Compiler.Steps
+{
+ public class ExpandComplexSlicingExpressions : MethodTrackingVisitorCompilerStep
+ {
+ public override void OnSlicingExpression(SlicingExpression node)
+ {
+ base.OnSlicingExpression(node);
+
+ if (!node.IsComplexSlicing())
+ return;
+
+ if (node.IsTargetOfAssignment())
+ return;
+
+ CompleteOmittedExpressions(node);
+ ExpandComplexSlicing(node);
+ }
+
+ void CompleteOmittedExpressions(SlicingExpression node)
+ {
+ foreach (var index in node.Indices.Where(slice => slice.Begin == OmittedExpression.Default))
+ index.Begin = CodeBuilder.CreateIntegerLiteral(0);
+ }
+
+ private void ExpandComplexSlicing(SlicingExpression node)
+ {
+ var targetType = GetExpressionType(node.Target);
+ if (IsString(targetType))
+ BindComplexStringSlicing(node);
+ else if (IsList(targetType))
+ BindComplexListSlicing(node);
+ else if (targetType.IsArray)
+ BindComplexArraySlicing(node);
+ else
+ NotImplemented(node, "complex slicing for anything but lists, arrays and strings");
+ }
+
+ private bool IsString(IType targetType)
+ {
+ return TypeSystemServices.StringType == targetType;
+ }
+
+ private bool IsList(IType targetType)
+ {
+ return IsAssignableFrom(TypeSystemServices.ListType, targetType);
+ }
+
+ void BindComplexListSlicing(SlicingExpression node)
+ {
+ var slice = node.Indices[0];
+
+ MethodInvocationExpression mie = null;
+ if (slice.End == null || slice.End == OmittedExpression.Default)
+ {
+ mie = CodeBuilder.CreateMethodInvocation(node.Target, MethodCache.List_GetRange1);
+ mie.Arguments.Add(slice.Begin);
+ }
+ else
+ {
+ mie = CodeBuilder.CreateMethodInvocation(node.Target, MethodCache.List_GetRange2);
+ mie.Arguments.Add(slice.Begin);
+ mie.Arguments.Add(slice.End);
+ }
+ node.ParentNode.Replace(node, mie);
+ }
+
+ void BindComplexArraySlicing(SlicingExpression node)
+ {
+ if (node.Indices.Count > 1)
+ {
+ MethodInvocationExpression mie = null;
+ var collapse = new ArrayLiteralExpression();
+ var ranges = new ArrayLiteralExpression();
+ for (int i = 0; i < node.Indices.Count; i++)
+ {
+ ranges.Items.Add(node.Indices[i].Begin);
+ if (node.Indices[i].End == null ||
+ node.Indices[i].End == OmittedExpression.Default)
+ {
+ var end = new BinaryExpression(BinaryOperatorType.Addition,
+ node.Indices[i].Begin,
+ new IntegerLiteralExpression(1));
+ ranges.Items.Add(end);
+ BindExpressionType(end, GetExpressionType(node.Indices[i].Begin));
+ collapse.Items.Add(new BoolLiteralExpression(true));
+ }
+ else
+ {
+ ranges.Items.Add(node.Indices[i].End);
+ collapse.Items.Add(new BoolLiteralExpression(false));
+ }
+ }
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges);
+ mie.Arguments.Add(collapse);
+
+ BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[])));
+ BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
+ node.ParentNode.Replace(node, mie);
+ }
+ else
+ {
+ Slice slice = node.Indices[0];
+ MethodInvocationExpression mie = null;
+
+ if (null == slice.End || slice.End == OmittedExpression.Default)
+ {
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_GetRange1, node.Target, slice.Begin);
+ }
+ else
+ {
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End);
+ }
+ node.ParentNode.Replace(node, mie);
+ }
+ }
+
+ static bool NeedsNormalization(Expression index)
+ {
+ return index.NodeType != NodeType.IntegerLiteralExpression || ((IntegerLiteralExpression) index).Value < 0;
+ }
+
+ void BindComplexStringSlicing(SlicingExpression node)
+ {
+ var slice = node.Indices[0];
+
+ MethodInvocationExpression mie = null;
+
+ if (null == slice.End || slice.End == OmittedExpression.Default)
+ {
+ if (NeedsNormalization(slice.Begin))
+ {
+ mie = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
+ mie.ExpressionType = TypeSystemServices.StringType;
+
+ InternalLocal temp = DeclareTempLocal(TypeSystemServices.StringType);
+ mie.Arguments.Add(
+ CodeBuilder.CreateAssignment(
+ CodeBuilder.CreateReference(temp),
+ node.Target));
+
+ mie.Arguments.Add(
+ CodeBuilder.CreateMethodInvocation(
+ CodeBuilder.CreateReference(temp),
+ MethodCache.String_Substring_Int,
+ CodeBuilder.CreateMethodInvocation(
+ MethodCache.RuntimeServices_NormalizeStringIndex,
+ CodeBuilder.CreateReference(temp),
+ slice.Begin)));
+ }
+ else
+ {
+ mie = CodeBuilder.CreateMethodInvocation(node.Target, MethodCache.String_Substring_Int, slice.Begin);
+ }
+ }
+ else
+ {
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_Mid, node.Target, slice.Begin, slice.End);
+ }
+
+ node.ParentNode.Replace(node, mie);
+ }
+
+ static bool IsAssignableFrom(IType expectedType, IType actualType)
+ {
+ return TypeCompatibilityRules.IsAssignableFrom(expectedType, actualType);
+ }
+
+ protected InternalLocal DeclareTempLocal(IType localType)
+ {
+ return CodeBuilder.DeclareTempLocal(CurrentMethod, localType);
+ }
+
+ protected RuntimeMethodCache MethodCache
+ {
+ get { return _methodCache.Instance; }
+ }
+
+ public override void Dispose()
+ {
+ _methodCache = new EnvironmentProvision<RuntimeMethodCache>();
+ base.Dispose();
+ }
+
+ private EnvironmentProvision<RuntimeMethodCache> _methodCache;
+ }
+}
View
18 src/Boo.Lang.Compiler/Steps/ExpandDuckTypedExpressions.cs
@@ -190,15 +190,9 @@ private static Expression GetSlicingTarget(SlicingExpression node)
private ArrayLiteralExpression GetArrayForIndices(SlicingExpression node)
{
- ArrayLiteralExpression args = new ArrayLiteralExpression();
- foreach (Slice index in node.Indices)
- {
- if (AstUtil.IsComplexSlice(index))
- {
- throw CompilerErrorFactory.NotImplemented(index, "complex slice for duck");
- }
+ var args = new ArrayLiteralExpression();
+ foreach (var index in node.Indices)
args.Items.Add(index.Begin);
- }
BindExpressionType(args, TypeSystemServices.ObjectArrayType);
return args;
}
@@ -271,12 +265,14 @@ override public void LeaveMemberReferenceExpression(MemberReferenceExpression no
void ProcessDuckSlicingPropertySet(BinaryExpression node)
{
- SlicingExpression slice = (SlicingExpression)node.Left;
+ var slice = (SlicingExpression)node.Left;
+ if (slice.IsComplexSlicing())
+ throw CompilerErrorFactory.NotImplemented(slice, "complex slicing for duck");
- ArrayLiteralExpression args = GetArrayForIndices(slice);
+ var args = GetArrayForIndices(slice);
args.Items.Add(node.Right);
- MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
+ var mie = CodeBuilder.CreateMethodInvocation(
node.LexicalInfo,
RuntimeServices_SetSlice,
GetSlicingTarget(slice),
View
26 src/Boo.Lang.Compiler/Steps/MethodTrackingVisitorCompilerStep.cs
@@ -0,0 +1,26 @@
+using Boo.Lang.Compiler.Ast;
+
+namespace Boo.Lang.Compiler.Steps
+{
+ public class MethodTrackingVisitorCompilerStep : AbstractFastVisitorCompilerStep
+ {
+ private Method _currentMethod;
+
+ public Method CurrentMethod
+ {
+ get { return _currentMethod; }
+ }
+
+ public override void OnMethod(Method node)
+ {
+ _currentMethod = node;
+ base.OnMethod(node);
+ }
+
+ public override void OnConstructor(Constructor node)
+ {
+ _currentMethod = node;
+ base.OnConstructor(node);
+ }
+ }
+}
View
340 src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs
@@ -84,6 +84,7 @@ public override void Initialize(CompilerContext context)
_memberStack = new Stack();
_callableResolutionService = new EnvironmentProvision<CallableResolutionService>();
_invocationTypeReferenceRules = new EnvironmentProvision<InvocationTypeInferenceRules>();
+ _typeChecker = new EnvironmentProvision<TypeChecker>();
_methodCache = new EnvironmentProvision<RuntimeMethodCache>();
}
@@ -1437,248 +1438,41 @@ override public void OnStringLiteralExpression(StringLiteralExpression node)
override public void OnCharLiteralExpression(CharLiteralExpression node)
{
- string value = node.Value;
- if (null == value || 1 != value.Length)
- {
- Errors.Add(CompilerErrorFactory.InvalidCharLiteral(node, value));
- }
+ CheckCharLiteralValue(node);
BindExpressionType(node, TypeSystemServices.CharType);
}
- IEntity[] GetSetMethods(IEntity[] entities)
- {
- List setMethods = new List();
- for (int i=0; i<entities.Length; ++i)
- {
- IProperty property = entities[i] as IProperty;
- if (null != property)
- {
- IMethod setter = property.GetSetMethod();
- if (null != setter)
- {
- setMethods.AddUnique(setter);
- }
- }
- }
- return ToEntityArray(setMethods);
- }
-
- IEntity[] GetGetMethods(IEntity[] entities)
- {
- List getMethods = new List();
- for (int i=0; i<entities.Length; ++i)
- {
- IProperty property = entities[i] as IProperty;
- if (null != property)
- {
- IMethod getter = property.GetGetMethod();
- if (null != getter)
- {
- getMethods.AddUnique(getter);
- }
- }
- }
- return ToEntityArray(getMethods);
- }
-
- private static IEntity[] ToEntityArray(List entities)
+ private void CheckCharLiteralValue(CharLiteralExpression node)
{
- return (IEntity[])entities.ToArray(new IEntity[entities.Count]);
+ var value = node.Value;
+ if (value == null || value.Length != 1)
+ Errors.Add(CompilerErrorFactory.InvalidCharLiteral(node, value));
}
- void CheckNoComplexSlicing(SlicingExpression node)
+ static IEntity[] GetSetMethods(IEntity[] entities)
{
- if (AstUtil.IsComplexSlicing(node))
- {
- NotImplemented(node, "complex slicing");
- }
+ return GetPropertyAccessors(entities, p => p.GetSetMethod());
}
- protected MethodInvocationExpression CreateEquals(BinaryExpression node)
+ private static IEntity[] GetGetMethods(IEntity[] entities)
{
- return CodeBuilder.CreateMethodInvocation(RuntimeServices_EqualityOperator, node.Left, node.Right);
+ return GetPropertyAccessors(entities, p => p.GetGetMethod());
}
- IntegerLiteralExpression CreateIntegerLiteral(long value)
+ private static IEntity[] GetPropertyAccessors(IEntity[] entities, Func<IProperty, IMethod> selector)
{
- IntegerLiteralExpression expression = new IntegerLiteralExpression(value);
- Visit(expression);
- return expression;
+ return entities.OfType<IProperty>().Select(selector).Distinct().ToArray<IEntity>();
}
- bool CheckComplexSlicingParameters(SlicingExpression node)
+ void AssertIsNotComplexSlicing(SlicingExpression node)
{
- foreach (Slice slice in node.Indices)
- {
- if (!CheckComplexSlicingParameters(slice))
- {
- return false;
- }
- }
- return true;
- }
-
- bool CheckComplexSlicingParameters(Slice node)
- {
- if (null != node.Step)
- {
- NotImplemented(node, "slicing step");
- return false;
- }
-
- if (OmittedExpression.Default == node.Begin)
- node.Begin = CreateIntegerLiteral(0);
- else if (!AssertTypeCompatibility(node.Begin, TypeSystemServices.IntType, GetExpressionType(node.Begin)))
- return false;
-
- if (null != node.End && OmittedExpression.Default != node.End)
- return AssertTypeCompatibility(node.End, TypeSystemServices.IntType, GetExpressionType(node.End));
-
- return true;
- }
-
- void BindComplexListSlicing(SlicingExpression node)
- {
- Slice slice = node.Indices[0];
-
- if (CheckComplexSlicingParameters(slice))
- {
- MethodInvocationExpression mie = null;
-
- if (null == slice.End || slice.End == OmittedExpression.Default)
- {
- mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange1);
- mie.Arguments.Add(slice.Begin);
- }
- else
- {
- mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange2);
- mie.Arguments.Add(slice.Begin);
- mie.Arguments.Add(slice.End);
- }
- node.ParentNode.Replace(node, mie);
- }
- }
-
- void BindComplexArraySlicing(SlicingExpression node)
- {
- if (AstUtil.IsLhsOfAssignment(node))
- {
- return;
- }
-
- if (CheckComplexSlicingParameters(node))
- {
- if (node.Indices.Count > 1)
- {
- IArrayType arrayType = (IArrayType)GetExpressionType(node.Target);
- MethodInvocationExpression mie = null;
- ArrayLiteralExpression collapse = new ArrayLiteralExpression();
- ArrayLiteralExpression ranges = new ArrayLiteralExpression();
- int collapseCount = 0;
- for (int i = 0; i < node.Indices.Count; i++)
- {
- ranges.Items.Add(node.Indices[i].Begin);
- if (node.Indices[i].End == null ||
- node.Indices[i].End == OmittedExpression.Default)
- {
- BinaryExpression end = new BinaryExpression(BinaryOperatorType.Addition,
- node.Indices[i].Begin,
- new IntegerLiteralExpression(1));
- ranges.Items.Add(end);
- BindExpressionType(end, GetExpressionType(node.Indices[i].Begin));
- collapse.Items.Add(new BoolLiteralExpression(true));
- collapseCount++;
- }
- else
- {
- ranges.Items.Add(node.Indices[i].End);
- collapse.Items.Add(new BoolLiteralExpression(false));
- }
- }
- mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges);
- mie.Arguments.Add(collapse);
-
- BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[])));
- BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
- BindExpressionType(mie, arrayType.ElementType.MakeArrayType(node.Indices.Count - collapseCount));
- node.ParentNode.Replace(node, mie);
- }
- else
- {
- Slice slice = node.Indices[0];
-
- if (CheckComplexSlicingParameters(slice))
- {
- MethodInvocationExpression mie = null;
-
- if (null == slice.End || slice.End == OmittedExpression.Default)
- {
- mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin);
- }
- else
- {
- mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End);
- }
-
- BindExpressionType(mie, GetExpressionType(node.Target));
- node.ParentNode.Replace(node, mie);
- }
- }
- }
+ if (node.IsComplexSlicing())
+ NotImplemented(node, "complex slicing");
}
- bool NeedsNormalization(Expression index)
+ protected MethodInvocationExpression CreateEquals(BinaryExpression node)
{
- if (NodeType.IntegerLiteralExpression == index.NodeType)
- {
- return ((IntegerLiteralExpression)index).Value < 0;
- }
- return true;
- }
-
- void BindComplexStringSlicing(SlicingExpression node)
- {
- Slice slice = node.Indices[0];
-
- if (CheckComplexSlicingParameters(slice))
- {
- MethodInvocationExpression mie = null;
-
- if (null == slice.End || slice.End == OmittedExpression.Default)
- {
- if (NeedsNormalization(slice.Begin))
- {
- mie = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
- mie.ExpressionType = TypeSystemServices.StringType;
-
- InternalLocal temp = DeclareTempLocal(TypeSystemServices.StringType);
- mie.Arguments.Add(
- CodeBuilder.CreateAssignment(
- CodeBuilder.CreateReference(temp),
- node.Target));
-
- mie.Arguments.Add(
- CodeBuilder.CreateMethodInvocation(
- CodeBuilder.CreateReference(temp),
- String_Substring_Int,
- CodeBuilder.CreateMethodInvocation(
- RuntimeServices_NormalizeStringIndex,
- CodeBuilder.CreateReference(temp),
- slice.Begin)));
- }
- else
- {
- mie = CodeBuilder.CreateMethodInvocation(node.Target, String_Substring_Int, slice.Begin);
- }
- }
- else
- {
- mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_Mid, node.Target, slice.Begin, slice.End);
- }
-
- node.ParentNode.Replace(node, mie);
- }
+ return CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_EqualityOperator, node.Left, node.Right);
}
protected bool IsIndexedProperty(Expression expression)
@@ -1702,36 +1496,21 @@ override public void LeaveSlicingExpression(SlicingExpression node)
return;
}
- if (IsIndexedProperty(node.Target))
+ if (node.IsComplexSlicing())
{
- BindIndexedPropertySlicing(node);
+ BindExpressionType(node, ResultingTypeForComplexSlicing(node));
return;
}
- if (targetType.IsArray)
+ if (IsIndexedProperty(node.Target))
{
- var arrayType = (IArrayType)targetType;
- if (arrayType.Rank != node.Indices.Count)
- Error(node,
- CompilerErrorFactory.InvalidArrayRank(node, node.Target.ToCodeString(), arrayType.Rank, node.Indices.Count));
-
- if (AstUtil.IsComplexSlicing(node))
- BindComplexArraySlicing(node);
- else
- BindExpressionType(node, arrayType.ElementType);
-
+ BindIndexedPropertySlicing(node);
return;
}
- if (AstUtil.IsComplexSlicing(node))
- {
- if (TypeSystemServices.StringType == targetType)
- BindComplexStringSlicing(node);
- else if (IsAssignableFrom(TypeSystemServices.ListType, targetType))
- BindComplexListSlicing(node);
- else
- NotImplemented(node, "complex slicing for anything but lists, arrays and strings");
-
+ if (targetType.IsArray)
+ {
+ BindExpressionType(node, targetType.ElementType);
return;
}
@@ -1750,21 +1529,27 @@ override public void LeaveSlicingExpression(SlicingExpression node)
SliceMember(node, member);
}
- private void BindIndexedPropertySlicing(SlicingExpression node)
+ private IType ResultingTypeForComplexSlicing(SlicingExpression node)
{
- CheckNoComplexSlicing(node);
- SliceMember(node, node.Target.Entity);
+ var targetType = GetExpressionType(node.Target);
+ return targetType.IsArray ? ResultingTypeForArraySlicing(node) : targetType;
}
- private bool IsAmbiguous(IEntity entity)
+ IType ResultingTypeForArraySlicing(SlicingExpression node)
{
- return null != entity && EntityType.Ambiguous == entity.EntityType;
+ var arrayType = GetExpressionType(node.Target);
+ if (node.Indices.Count > 1)
+ {
+ var collapseCount = node.Indices.Count(t => t.End == null || t.End == OmittedExpression.Default);
+ return arrayType.ElementType.MakeArrayType(node.Indices.Count - collapseCount);
+ }
+ return arrayType;
}
- bool IsIndexedProperty(IEntity tag)
+ private void BindIndexedPropertySlicing(SlicingExpression node)
{
- return EntityType.Property == tag.EntityType &&
- ((IProperty)tag).GetParameters().Length > 0;
+ AssertIsNotComplexSlicing(node);
+ SliceMember(node, node.Target.Entity);
}
void SliceMember(SlicingExpression node, IEntity member)
@@ -2955,7 +2740,7 @@ void ExpandIncrementDecrement(UnaryExpression node)
Expression ExpandIncrementDecrementArraySlicing(UnaryExpression node)
{
SlicingExpression slicing = (SlicingExpression)node.Operand;
- CheckNoComplexSlicing(slicing);
+ AssertIsNotComplexSlicing(slicing);
Visit(slicing);
return CreateSideEffectAwareSlicingOperation(
node.LexicalInfo,
@@ -4642,8 +4427,7 @@ void BindAssignmentToSliceArray(BinaryExpression node)
BindAssignmentToComplexSliceArray(node);
return;
}
-
- CheckArrayIndices(slice);
+
var elementType = GetExpressionType(slice.Target).ElementType;
var expressionType = GetExpressionType(node.Right);
if (!AssertTypeCompatibility(node.Right, elementType, expressionType))
@@ -4654,12 +4438,6 @@ void BindAssignmentToSliceArray(BinaryExpression node)
node.ExpressionType = elementType;
}
- private void CheckArrayIndices(SlicingExpression slice)
- {
- foreach (var item in slice.Indices)
- AssertTypeCompatibility(item.Begin, TypeSystemServices.IntType, GetExpressionType(item.Begin));
- }
-
void BindAssignmentToComplexSliceArray(BinaryExpression node)
{
var slice = (SlicingExpression)node.Left;
@@ -5389,24 +5167,21 @@ protected virtual void NamedArgumentNotFound(IType type, ReferenceExpression nam
bool AssertTypeCompatibility(Node sourceNode, IType expectedType, IType actualType)
{
- if (IsError(expectedType) || IsError(actualType))
- return false;
-
- if (expectedType.IsPointer && actualType.IsPointer)
- return true; //if both types are unmanaged pointers casting is always possible
-
- if (TypeSystemServices.IsNullable(expectedType) && actualType.IsNull())
- return true;
+ return TypeChecker.AssertTypeCompatibility(sourceNode, expectedType, actualType);
+ }
- if (!CanBeReachedFrom(sourceNode, expectedType, actualType))
- {
- Error(CompilerErrorFactory.IncompatibleExpressionType(sourceNode, expectedType, actualType));
- return false;
- }
+ bool CanBeReachedFrom(Node anchor, IType expectedType, IType actualType)
+ {
+ return TypeChecker.CanBeReachedFrom(anchor, expectedType, actualType);
+ }
- return true;
+ private TypeChecker TypeChecker
+ {
+ get { return _typeChecker.Instance; }
}
+ private EnvironmentProvision<TypeChecker> _typeChecker;
+
bool AssertDelegateArgument(Node sourceNode, ITypedEntity delegateMember, ITypedEntity argumentInfo)
{
if (!IsAssignableFrom(delegateMember.Type, argumentInfo.Type))
@@ -6151,19 +5926,6 @@ void InvalidOperatorForTypes(BinaryExpression node)
GetExpressionType(node.Right)));
}
- bool CanBeReachedFrom(Node anchor, IType expectedType, IType actualType)
- {
- bool byDowncast;
- bool result = TypeSystemServices.CanBeReachedFrom(expectedType, actualType, out byDowncast);
- if (!result)
- return false;
-
- if (byDowncast)
- Warnings.Add(CompilerWarningFactory.ImplicitDowncast(anchor, expectedType, actualType));
-
- return true;
- }
-
void TraceReturnType(Method method, IMethod tag)
{
_context.TraceInfo("{0}: return type for method {1} bound to {2}", method.LexicalInfo, method.Name, tag.ReturnType);
View
46 src/Boo.Lang.Compiler/TypeSystem/Services/TypeChecker.cs
@@ -0,0 +1,46 @@
+using Boo.Lang.Compiler.Ast;
+using Boo.Lang.Environments;
+
+namespace Boo.Lang.Compiler.TypeSystem.Services
+{
+ public class TypeChecker
+ {
+ private readonly EnvironmentProvision<TypeSystemServices> _typeSystemServices;
+ private readonly EnvironmentProvision<CompilerErrorCollection> _errors;
+ private readonly EnvironmentProvision<CompilerWarningCollection> _warnings;
+
+ public bool AssertTypeCompatibility(Node sourceNode, IType expectedType, IType actualType)
+ {
+ if (IsError(expectedType) || IsError(actualType))
+ return false;
+
+ if (expectedType.IsPointer && actualType.IsPointer)
+ return true; //if both types are unmanaged pointers casting is always possible
+
+ if (TypeSystemServices.IsNullable(expectedType) && actualType.IsNull())
+ return true;
+
+ if (!CanBeReachedFrom(sourceNode, expectedType, actualType))
+ {
+ _errors.Instance.Add(CompilerErrorFactory.IncompatibleExpressionType(sourceNode, expectedType, actualType));
+ return false;
+ }
+ return true;
+ }
+
+ public bool CanBeReachedFrom(Node anchor, IType expectedType, IType actualType)
+ {
+ bool byDowncast;
+ if (!_typeSystemServices.Instance.CanBeReachedFrom(expectedType, actualType, out byDowncast))
+ return false;
+ if (byDowncast)
+ _warnings.Instance.Add(CompilerWarningFactory.ImplicitDowncast(anchor, expectedType, actualType));
+ return true;
+ }
+
+ private static bool IsError(IEntity entity)
+ {
+ return TypeSystemServices.IsError(entity);
+ }
+ }
+}
View
2  src/Boo.Lang.Interpreter/Builtins/repr.boo
@@ -55,7 +55,7 @@ static class Repr:
Boo.Lang.Compiler.Ast.Visitors.BooPrinterVisitor.WriteStringLiteral(value, writer)
AddRepresenter(bool) do (value as bool, writer as TextWriter):
- writer.Write(("false", "true")[value])
+ writer.Write(("true" if value else "false"))
AddRepresenter(Array) do (a as Array, writer as TextWriter):
writer.Write("(")
View
2  src/Boo.Lang.Interpreter/InteractiveInterpreterConsole.boo
@@ -580,7 +580,7 @@ Enter boo code in the prompt below (or type /help)."""
WithColor color:
for problem as duck in problems:
markLocation(problem.LexicalInfo)
- type = ("WARNING", "ERROR")[problem isa CompilerError]
+ type = ("ERROR" if problem isa CompilerError else "WARNING")
Console.WriteLine("${type}: ${problem.Message}")
return true
View
12 tests/BooCompiler.Tests/CompilerErrorsTestFixture.cs
@@ -1341,6 +1341,12 @@ public void error_doesnt_cascade_to_raise()
}
[Test]
+ public void invalid_array_slice()
+ {
+ RunCompilerTestCase(@"invalid-array-slice.boo");
+ }
+
+ [Test]
public void invalid_generic_extension_1()
{
RunCompilerTestCase(@"invalid-generic-extension-1.boo");
@@ -1353,6 +1359,12 @@ public void invalid_generic_extension_2()
}
[Test]
+ public void invalid_matrix_index()
+ {
+ RunCompilerTestCase(@"invalid-matrix-index.boo");
+ }
+
+ [Test]
public void mismatched_collection_initializers()
{
RunCompilerTestCase(@"mismatched-collection-initializers.boo");
View
6 tests/testcases/errors/invalid-array-slice.boo
@@ -0,0 +1,6 @@
+"""
+invalid-array-slice.boo(6,9): BCE0022: Cannot convert 'bool' to 'int'.
+invalid-array-slice.boo(6,15): BCE0022: Cannot convert 'bool' to 'int'.
+"""
+a = (1, 2, 3)
+print a[false:true]
View
11 tests/testcases/errors/invalid-matrix-index.boo
@@ -0,0 +1,11 @@
+"""
+invalid-matrix-index.boo(10,3): BCE0022: Cannot convert 'S' to 'int'.
+invalid-matrix-index.boo(10,6): BCE0022: Cannot convert 'S' to 'int'.
+"""
+struct S:
+ i as int
+
+m = matrix of int(2, 2)
+s = S(i: 42)
+m[s, s] = 0
+
Please sign in to comment.
Something went wrong with that request. Please try again.