Skip to content

Commit

Permalink
Merge pull request #84 from MoeOrganization/prakashk/array-slice-and-…
Browse files Browse the repository at this point in the history
…stuff

Array slicing by range/another array and other stuff
  • Loading branch information
Stevan Little committed Apr 24, 2013
2 parents 9eb55ac + 2217345 commit ee819ad
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 14 deletions.
15 changes: 15 additions & 0 deletions spec/examples/99-problems/17.mo
@@ -0,0 +1,15 @@
# P17 (*) Split a list into two parts.
# The length of the first part is given.

# Example:

# moe> split_list(3, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"])
# [["a", "b", "c"], ["d", "e", "f", "g", "h", "i", "j", "k"]]

sub split_list($n, @list) {
# XXXX: the range expressions should work without enclosing parens too!
[@list[0..($n-1)], @list[$n..(@list.length-1)]]
}

say split_list(3, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]);

16 changes: 16 additions & 0 deletions spec/examples/99-problems/18.mo
@@ -0,0 +1,16 @@
# P18 (**) Extract a slice from a list.
# Given two indices, I and K, the slice is the list containing the
# elements from and including the Ith element up to but not
# including the Kth element of the original list. Start counting
# the elements with 0.

# Example:

# moe> slice(3, 7, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"])
# ["d", "e", "f", "g"]

sub slice_list($s, $e, @list) {
# XXXX: the range operand without enclosing parens should work too!
@list[$s .. ($e-1)]
}
say slice_list(3, 7, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]);
18 changes: 18 additions & 0 deletions spec/examples/99-problems/19.mo
@@ -0,0 +1,18 @@
# P19 (**) Rotate a list N places to the left.
# Examples:

# moe> rotate(3, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"])
# ["d", "e", "f", "g", "h", "i", "j", "k", "a", "b", "c""]

# moe> rotate(-2, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"])
# ["j", "k", "a", "b", "c", "d", "e", "f", "g", "h", "i"]

sub rotate($n, @list) {
my $len = @list.length;
my @r = @list[($n < 0 ? $len + $n : $n) .. ($len - 1)];
@r.push(@list[0 .. ($n < 0 ? $len + $n : $n-1)]);
@r.flatten
}

say rotate(3, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]);
say rotate(-2, ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]);
16 changes: 16 additions & 0 deletions spec/examples/99-problems/20.mo
@@ -0,0 +1,16 @@
# P20 (*) Remove the Kth element from a list.
# Return the list and the removed element in a Tuple. Elements are numbered from 0.

# Example:

# moe> remove_at(1, ['a', 'b', 'c', 'd'])
# [['a', 'c', 'd'],'b']

sub remove_at($i, @list) {
my $removed = @list[$i];
my @rest = @list[0 .. ($i-1)];
@rest.push(@list[($i+1) .. (@list.length-1)]);
[@rest.flatten, $removed]
}

say remove_at(1, ['a', 'b', 'c', 'd']);
13 changes: 13 additions & 0 deletions spec/examples/99-problems/21.mo
@@ -0,0 +1,13 @@
# P21 (*) Insert an element at a given position into a list.
# Example:

# moe> insert_at('new', 1, ['a', 'b', 'c', 'd'])
# ['a', 'new', 'b', 'c', 'd')

sub insert_at($new, $at, @list) {
my @r = @list[0 .. ($at-1)];
@r.push($new, @list[$at .. (@list.length-1)]);
@r.flatten
}

say insert_at('new', 1, ['a', 'b', 'c', 'd'])
10 changes: 10 additions & 0 deletions spec/examples/99-problems/22.mo
@@ -0,0 +1,10 @@
# P22 (*) Create a list containing all integers within a given range.
# Example:

# moe> range(4, 9)
# [4, 5, 6, 7, 8, 9]

sub range($start, $end) { $start .. $end }

say range(4, 9)

13 changes: 11 additions & 2 deletions src/main/scala/org/moe/interpreter/Interpreter.scala
Expand Up @@ -93,10 +93,19 @@ class Interpreter {
case _ => throw new MoeErrors.UnexpectedType("MoeArrayObject expected")
}

import scala.util.{Try, Success, Failure}
indices.foldLeft[MoeObject](array_value) {
(a, i) =>
(array, i) =>
val index = eval(runtime, env, i)
callMethod(a, "postcircumfix:<[]>", List(index), "Array")
index match {
case i: MoeIntObject => callMethod(array, "postcircumfix:<[]>", List(i), "Array")
case r: MoeObject => {
r.unboxToArrayBuffer match {
case Success(a) => callMethod(array, "slice", a.toList, "Array")
case _ => callMethod(array, "slice", List(r), "Array")
}
}
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/main/scala/org/moe/parser/MoeParser.scala
Expand Up @@ -22,5 +22,19 @@ object MoeParser extends MoeProductions {
}

def parseStuff(input: String): StatementsNode = parseFromEntry(input)

// helper method to test with any parser combinator
def testParser(input: String, parser: Parser[AST] = getEntryPoint): AST = {
def error_msg(msg: String, next: Input) = "[" + next.pos + "] error: " + msg + "\n\n" + next.pos.longString

parseAll(parser, input) match {
case Success(result, _) => result
case NoSuccess(msg, next) => if (next.atEnd)
throw new MoeErrors.ParserInputIncomplete(error_msg(msg, next))
else
throw new MoeErrors.ParserInputError(error_msg(msg, next))
}
}

}

13 changes: 1 addition & 12 deletions src/main/scala/org/moe/parser/MoeProductions.scala
Expand Up @@ -191,18 +191,7 @@ trait MoeProductions extends MoeLiterals with JavaTokenParsers with PackratParse

// Range Literals

def rangeOperands: Parser[AST] = (
floatNumber
| intNumber
| octIntNumber
| hexIntNumber
| binIntNumber
| zeroNumber
| string
| variable
)

def range: Parser[RangeLiteralNode] = rangeOperands ~ ".." ~ rangeOperands ^^ {
def range: Parser[RangeLiteralNode] = simpleExpression ~ ".." ~ simpleExpression ^^ {
case s ~ _ ~ e => RangeLiteralNode(s, e)
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/scala/org/moe/parser/RangeLiteralTestSuite.scala
Expand Up @@ -92,4 +92,12 @@ class RangeLiteralTestSuite extends FunSuite with BeforeAndAfter with ParserTest
assert(array.size === 0)
}

test("... basic test with expressions as range operands") {
val result = interpretCode(""" my $a = 2; my $b = 6; ($a+1)..($b-1) """)
val array = result.unboxToArrayBuffer.get
assert(array.size === 3)
assert(array(0).unboxToString.get === "3")
assert(array(1).unboxToString.get === "4")
assert(array(2).unboxToString.get === "5")
}
}

0 comments on commit ee819ad

Please sign in to comment.