Skip to content

Commit

Permalink
equality and relational operators for strings; compare operator for i…
Browse files Browse the repository at this point in the history
…nts and strings
  • Loading branch information
prakashk committed Mar 19, 2013
1 parent e1b7b0c commit 34e680e
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 15 deletions.
12 changes: 8 additions & 4 deletions src/main/scala/org/moe/parser/Expressions.scala
Expand Up @@ -30,7 +30,7 @@ trait Expressions extends Literals with JavaTokenParsers with PackratParsers {
// TODO: right ?:


// left || //
// left || TODO: //
lazy val logicalOrOp: PackratParser[AST] = logicalOrOp ~ """\|\||//""".r ~ logicalAndOp ^^ {
case left ~ op ~ right => ShortCircuitBinaryOpNode(left, op, right)
} | logicalAndOp
Expand All @@ -46,13 +46,17 @@ trait Expressions extends Literals with JavaTokenParsers with PackratParsers {
} | bitAndOp

// left &
lazy val bitAndOp: PackratParser[AST] = bitAndOp ~ "&" ~ relOp ^^ {
lazy val bitAndOp: PackratParser[AST] = bitAndOp ~ "&" ~ eqOp ^^ {
case left ~ op ~ right => BinaryOpNode(left, op, right)
} | eqOp

// nonassoc == != eq ne cmp ~~
lazy val eqOp: PackratParser[AST] = eqOp ~ "[!=]=|<=>|eq|ne|cmp".r ~ relOp ^^ {
case left ~ op ~ right => BinaryOpNode(left, op, right)
} | relOp

// nonassoc == != <=> eq ne cmp ~~
// nonassoc < > <= >= lt gt le ge
lazy val relOp: PackratParser[AST] = relOp ~ "[<>]=?|[!=]=".r ~ addOp ^^ {
lazy val relOp: PackratParser[AST] = relOp ~ "[<>]=?|lt|gt|le|ge".r ~ addOp ^^ {
case left ~ op ~ right => BinaryOpNode(left, op, right)
} | addOp

Expand Down
11 changes: 11 additions & 0 deletions src/main/scala/org/moe/runtime/builtins/IntClass.scala
Expand Up @@ -180,6 +180,8 @@ object IntClass {
)
)

// equality operators

intClass.addMethod(
new MoeMethod(
"infix:<==>",
Expand All @@ -198,6 +200,15 @@ object IntClass {
)
)

intClass.addMethod(
new MoeMethod(
"infix:<<=>>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeIntObject].compare_to(r, e.get("$other").get)
)
)

// bitwise operators

intClass.addMethod(
Expand Down
67 changes: 66 additions & 1 deletion src/main/scala/org/moe/runtime/builtins/StrClass.scala
Expand Up @@ -47,7 +47,72 @@ object StrClass {
)
)

// operators
// relational operators

strClass.addMethod(
new MoeMethod(
"infix:<lt>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].less_than(r, e.get("$other").get)
)
)

strClass.addMethod(
new MoeMethod(
"infix:<gt>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].greater_than(r, e.get("$other").get)
)
)

strClass.addMethod(
new MoeMethod(
"infix:<le>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].less_than_or_equal_to(r, e.get("$other").get)
)
)

strClass.addMethod(
new MoeMethod(
"infix:<ge>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].greater_than_or_equal_to(r, e.get("$other").get)
)
)

// equality operators

strClass.addMethod(
new MoeMethod(
"infix:<eq>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].equal_to(r, e.get("$other").get)
)
)

strClass.addMethod(
new MoeMethod(
"infix:<ne>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].not_equal_to(r, e.get("$other").get)
)
)

strClass.addMethod(
new MoeMethod(
"infix:<cmp>",
new MoeSignature(List(new MoeParameter("$other"))),
env,
(e) => e.getCurrentInvocant.get.asInstanceOf[MoeStrObject].compare_to(r, e.get("$other").get)
)
)

// methods

Expand Down
Expand Up @@ -64,6 +64,12 @@ class MoeIntObject(
case _ => throw new MoeErrors.UnexpectedType(other.toString)
}

def compare_to (r: MoeRuntime, other: MoeObject): MoeIntObject = other match {
case i: MoeIntObject => r.NativeObjects.getInt(getNativeValue compareTo i.unboxToInt.get)
case f: MoeNumObject => r.NativeObjects.getInt(unboxToDouble.get compareTo f.unboxToDouble.get)
case _ => throw new MoeErrors.UnexpectedType(other.toString)
}

// comparison

def less_than (r: MoeRuntime, other: MoeObject): MoeBoolObject = other match {
Expand Down
30 changes: 30 additions & 0 deletions src/main/scala/org/moe/runtime/nativeobjects/MoeStrObject.scala
Expand Up @@ -64,6 +64,36 @@ class MoeStrObject(
r.NativeObjects.getStr(List.fill(n)(str).mkString)
}

// equality

def equal_to (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue == other.unboxToString.get)

def not_equal_to (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue != other.unboxToString.get)

def compare_to (r: MoeRuntime, other: MoeObject): MoeIntObject =
r.NativeObjects.getInt(
getNativeValue compareTo other.unboxToString.get match {
case 0 => 0
case r => if (r < 0) -1 else 1
}
)

// comparison

def less_than (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue < other.unboxToString.get)

def greater_than (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue > other.unboxToString.get)

def less_than_or_equal_to (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue <= other.unboxToString.get)

def greater_than_or_equal_to (r: MoeRuntime, other: MoeObject): MoeBoolObject =
r.NativeObjects.getBool(getNativeValue >= other.unboxToString.get)

// MoeObject overrides

override def isFalse: Boolean = getNativeValue match {
Expand Down
99 changes: 99 additions & 0 deletions src/test/scala/org/moe/parser/SimpleExpressionStrTestSuite.scala
Expand Up @@ -41,4 +41,103 @@ class SimpleExpressionStrTestSuite extends FunSuite with BeforeAndAfter with Par
result.unboxToString.get should equal ("MoeMoeMoeMoeMoe")
}

// equality operators

test("""... literal string equality operation ... ["Moe" eq "Moe"]""") {
val result = interpretCode(""""Moe" eq "Moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string equality operation ... ["Moe" eq "moe"]""") {
val result = interpretCode(""""Moe" eq "moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string equality operation ... ["Moe" ne "Moe"]""") {
val result = interpretCode(""""Moe" ne "Moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string equality operation ... ["Moe" ne "moe"]""") {
val result = interpretCode(""""Moe" ne "moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string equality operation ... ["Moe" cmp "moe"]""") {
val result = interpretCode(""""Moe" cmp "moe"""")
result.unboxToInt.get should equal (-1)
}

test("""... literal string equality operation ... ["Moe" cmp "Moe"]""") {
val result = interpretCode(""""Moe" cmp "Moe"""")
result.unboxToInt.get should equal (0)
}

test("""... literal string equality operation ... ["moe" cmp "Moe"]""") {
val result = interpretCode(""""moe" cmp "Moe"""")
result.unboxToInt.get should equal (1)
}

// relational operators

test("""... literal string relational operation lt ... ["Moe" lt "moe"]""") {
val result = interpretCode(""""Moe" lt "moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string relational operation lt ... ["moe" lt "Moe"]""") {
val result = interpretCode(""""moe" lt "Moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation lt ... ["Moe" lt "Moe"]""") {
val result = interpretCode(""""Moe" lt "Moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation gt ... ["Moe" gt "moe"]""") {
val result = interpretCode(""""Moe" gt "moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation gt ... ["moe" gt "Moe"]""") {
val result = interpretCode(""""moe" gt "Moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string relational operation gt ... ["Moe" gt "Moe"]""") {
val result = interpretCode(""""Moe" gt "Moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation le ... ["Moe" le "Moe"]""") {
val result = interpretCode(""""Moe" le "Moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string relational operation le ... ["Moe" le "moe"]""") {
val result = interpretCode(""""Moe" le "moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string relational operation le ... ["moe" le "Moe"]""") {
val result = interpretCode(""""moe" le "Moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation ge ... ["Moe" ge "Moe"]""") {
val result = interpretCode(""""Moe" ge "Moe"""")
result.unboxToBoolean.get should equal (true)
}

test("""... literal string relational operation ge ... ["Moe" ge "moe"]""") {
val result = interpretCode(""""Moe" ge "moe"""")
result.unboxToBoolean.get should equal (false)
}

test("""... literal string relational operation ge ... ["moe" ge "Moe"]""") {
val result = interpretCode(""""moe" ge "Moe"""")
result.unboxToBoolean.get should equal (true)
}

}
37 changes: 27 additions & 10 deletions src/test/scala/org/moe/parser/SimpleExpressionTestSuite.scala
Expand Up @@ -285,6 +285,33 @@ class SimpleExpressionTestSuite extends FunSuite with BeforeAndAfter with Parser
result.unboxToInt.get should not equal (4096)
}

// equality operators

test("... literal int equality operation ... [2 == 2]") {
val result = interpretCode("2 == 2")
result.unboxToBoolean.get should equal (true)
}

test("... literal int equality operation ... [2 != 2]") {
val result = interpretCode("2 != 2")
result.unboxToBoolean.get should equal (false)
}

test("... literal int equality operation ... [2 <=> 3]") {
val result = interpretCode("2 <=> 3")
result.unboxToInt.get should equal (-1)
}

test("... literal int equality operation ... [2 <=> 2]") {
val result = interpretCode("2 <=> 2")
result.unboxToInt.get should equal (0)
}

test("... literal int equality operation ... [3 <=> 2]") {
val result = interpretCode("3 <=> 2")
result.unboxToInt.get should equal (1)
}

// relational operators

test("... literal int relational operation #1 ... [1 < 2]") {
Expand Down Expand Up @@ -347,16 +374,6 @@ class SimpleExpressionTestSuite extends FunSuite with BeforeAndAfter with Parser
result.unboxToBoolean.get should equal (false)
}

test("... literal int relational operation #13 ... [2 == 2]") {
val result = interpretCode("2 == 2")
result.unboxToBoolean.get should equal (true)
}

test("... literal int relational operation #14 ... [2 != 2]") {
val result = interpretCode("2 != 2")
result.unboxToBoolean.get should equal (false)
}

test("... literal int relational operation #15 ... [2 >= 2]") {
val result = interpretCode("2 >= 2")
result.unboxToBoolean.get should equal (true)
Expand Down

0 comments on commit 34e680e

Please sign in to comment.