Skip to content

Commit

Permalink
better slicing semantics for strings
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.codehaus.org/boo/trunk@965 2c1201b4-01cd-e047-a400-b836ae1fbc61
  • Loading branch information
bamboo committed Sep 10, 2004
1 parent cb8ccb9 commit 2dcea69
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
3 changes: 3 additions & 0 deletions il
@@ -0,0 +1,3 @@
#!/bin/sh

mono build/booc.exe -out:build/il.exe "$@" && monodis build/il.exe
2 changes: 1 addition & 1 deletion il.bat
@@ -1,3 +1,3 @@
@echo off
build\booc.exe /out:build\il.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
build\booc.exe -out:build\il.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
ildasm /text build\il.exe
52 changes: 49 additions & 3 deletions src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs
Expand Up @@ -59,6 +59,8 @@ public class ProcessMethodBodies : AbstractNamespaceSensitiveVisitorCompilerStep

IMethod RuntimeServices_Mid;

IMethod RuntimeServices_NormalizeStringIndex;

IMethod RuntimeServices_GetRange1;

IMethod RuntimeServices_GetRange2;
Expand Down Expand Up @@ -152,7 +154,8 @@ virtual protected void InitializeMemberCache()
RuntimeServices_GetRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange1");
RuntimeServices_GetRange2 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange2");
RuntimeServices_Len = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Len");
RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
RuntimeServices_NormalizeStringIndex = ResolveMethod(TypeSystemServices.RuntimeServicesType, "NormalizeStringIndex");
RuntimeServices_GetEnumerable = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetEnumerable");
RuntimeServices_op_Equality = (IMethod)TypeSystemServices.Map(Types.RuntimeServices.GetMethod("op_Equality", new Type[] { Types.Object, Types.Object }));
Array_get_Length = ResolveProperty(TypeSystemServices.ArrayType, "Length").GetGetMethod();
Expand Down Expand Up @@ -1279,6 +1282,15 @@ void BindComplexArraySlicing(SlicingExpression node)
}
}

bool NeedsNormalization(Expression index)
{
if (NodeType.IntegerLiteralExpression == index.NodeType)
{
return ((IntegerLiteralExpression)index).Value < 0;
}
return true;
}

void BindComplexStringSlicing(SlicingExpression node)
{
if (CheckComplexSlicingParameters(node))
Expand All @@ -1287,8 +1299,30 @@ void BindComplexStringSlicing(SlicingExpression node)

if (null == node.End || node.End == OmittedExpression.Default)
{
mie = CodeBuilder.CreateMethodInvocation(node.Target, String_Substring_Int);
mie.Arguments.Add(node.Begin);
if (NeedsNormalization(node.Begin))
{
mie = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
mie.ExpressionType = TypeSystemServices.StringType;

LocalVariable 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),
node.Begin)));
}
else
{
mie = CodeBuilder.CreateMethodInvocation(node.Target, String_Substring_Int, node.Begin);
}
}
else
{
Expand Down Expand Up @@ -3867,6 +3901,18 @@ ReferenceExpression CreateTempLocal(LexicalInfo li, IType type)
return reference;
}

LocalVariable DeclareTempLocal(IType localType)
{
Local local = new Local();
local.Name = "___temp" + _context.AllocIndex();
local.PrivateScope = true;

LocalVariable entity = new LocalVariable(local, localType);
local.Entity = entity;
_currentMethod.Method.Locals.Add(local);
return entity;
}

LocalVariable DeclareLocal(Node sourceNode, Local local, IType localType)
{
LocalVariable tag = new LocalVariable(local, localType);
Expand Down
15 changes: 7 additions & 8 deletions src/Boo/Lang/RuntimeServices.cs
Expand Up @@ -134,14 +134,8 @@ public static int Len(object obj)

public static string Mid(string s, int begin, int end)
{
if (begin < 0)
{
begin += s.Length;
}
if (end < 0)
{
end += s.Length;
}
begin = NormalizeStringIndex(s, begin);
end = NormalizeStringIndex(s, end);
return s.Substring(begin, end-begin);
}

Expand Down Expand Up @@ -184,6 +178,11 @@ public static int NormalizeArrayIndex(Array array, int index)
return index < 0 ? array.Length + index : index;
}

public static int NormalizeStringIndex(string s, int index)
{
return index < 0 ? s.Length + index : index;
}

public static IEnumerable GetEnumerable(object enumerable)
{
if (null == enumerable)
Expand Down
9 changes: 9 additions & 0 deletions tests/testcases/integration/slicing-11.boo
@@ -0,0 +1,9 @@
import NUnit.Framework

a = "Gooooooooood niiiiiiiiigh ding ding ding ding ding ding"
Assert.AreEqual("Go", a[:2])
Assert.AreEqual("Go", a[0:2])
Assert.AreEqual("ding", a[-4:])
Assert.AreEqual("din", a[-4:-1])


0 comments on commit 2dcea69

Please sign in to comment.