Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

String methods #270

Open
wants to merge 12 commits into
base: q2
Choose a base branch
from
10 changes: 7 additions & 3 deletions quarkc/emit_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,10 @@ def code_assert(assrt, expected, actual, op, target):

@match(choice(AssertEqual, AssertNotEqual), Expression, Expression, basestring, Go)
def code_assert(assrt, expected, actual, op, target):
if op == "==":
op = "reflect.DeepEqual"
else:
op = "!reflect.DeepEqual"
return tr.Compound("", tr.Block(
tr.Comment(repr(assrt)),
tr.Simple("var expected {type} = {expected}".format(
Expand All @@ -644,7 +648,7 @@ def code_assert(assrt, expected, actual, op, target):
tr.Simple("var actual {type} = {actual}".format(
type = "interface{}",
actual = expr(assrt.actual, target))),
tr.Compound("if (!(expected {op} actual))".format(op=op), tr.Block(
tr.Compound("if (!({op}(expected, actual)))".format(op=op), tr.Block(
tr.Simple("t__.Error(\"assert(\", expected, \"{op}\", actual, \")\")".format(op=op))))))

@match(AssertEqual, Python)
Expand All @@ -667,7 +671,7 @@ def code(assrt, target):

@match(AssertEqual, Javascript)
def code(assrt, target):
return tr.Simple("assert.strictEqual(({expected}), ({actual}))".format(
return tr.Simple("assert.deepStrictEqual(({expected}), ({actual}))".format(
expected = expr(assrt.expected, target),
actual = expr(assrt.actual, target)))

Expand Down Expand Up @@ -698,7 +702,7 @@ def code(assrt, target):

@match(AssertNotEqual, Javascript)
def code(assrt, target):
return tr.Simple("assert.notStrictEqual(({expected}), ({actual}))".format(
return tr.Simple("assert.notDeepStrictEqual(({expected}), ({actual}))".format(
expected = expr(assrt.expected, target),
actual = expr(assrt.actual, target)))

Expand Down
2 changes: 1 addition & 1 deletion quarkc/emit_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def header(dfn, target):
tr.Simple("package {name}".format(
name = target.nameof(dfn)
)),
tr.Simple("import \"testing\"")
tr.Simple('import "testing"\nimport "reflect"')
)) + tuple(imports(dfn, target))

@match(Definition, Python)
Expand Down
80 changes: 79 additions & 1 deletion quarkc/lib/quark.q
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,15 @@ namespace quark {
bool __eq__(String other);
int size();
String substring(int start, int end);

String strip();
bool startsWith(String other);
bool endsWith(String other);
int find(String other);
String replaceAll(String from, String to);
String join(List<String> parts);
List<String> split(String sep);
String toUpper();
String toLower();

String __add__(String other) for java { return $self + $other; }
bool __eq__(String other) for java { return $self.equals($other); }
Expand All @@ -1372,6 +1380,32 @@ namespace quark {
int l = $self.length();
return $self.substring($start, $end < l ? $end : l);
}
String strip() for java { return ($self).trim(); }
bool startsWith(String other) for java { return Boolean.valueOf(($self).startsWith($other)); }
bool endsWith(String other) for java { return Boolean.valueOf(($self).endsWith($other)); }
int find(String other) for java { return ($self).indexOf($other); }
String replaceAll(String from, String to) for java import "java.util.regex.Pattern" {
return ($self).replaceAll(Pattern.quote($from), ($to));
}
List<String> split(String sep) for java import "java.util.ArrayList"
import "java.util.Arrays"
import "java.util.regex.Pattern" {
return new ArrayList<String>(Arrays.asList(($self).split(Pattern.quote($sep), -1))); }
String join(List<String> parts) for java {
StringBuilder b = new StringBuilder();
boolean first = true;
for (String part : $parts) {
if (first) {
first = false;
} else {
b.append($self);
}
b.append(part);
}
return b.toString();
}
String toUpper() for java { return ($self).toUpperCase(); }
String toLower() for java { return ($self).toLowerCase(); }


String __add__(String other) for go { return $self + $other }
Expand All @@ -1392,23 +1426,67 @@ namespace quark {
}
return $self[s:e]
}
String strip() for go import "strings" { return strings.TrimSpace($self) }
bool startsWith(String other) for go import "strings" { return strings.HasPrefix(($self), ($other)) }
bool endsWith(String other) for go import "strings" { return strings.HasSuffix(($self), ($other)) }
int find(String other) for go import "strings" { return strings.Index($self, $other) }
String replaceAll(String from, String to) for go import "strings" { return strings.Replace($self, $from, $to, -1) }
List<String> split(String sep) for go import "strings" {
l := strings.Split($self, $sep)
return &l
}
String join(List<String> parts) for go import "strings" { return strings.Join(*($parts), $self)}
String toUpper() for go import "strings"{ return strings.ToUpper($self) }
String toLower() for go import "strings" { return strings.ToLower($self) }

String __add__(String other) for python { return $self + $other }
bool __eq__(String other) for python { return $self == $other }
int size() for python { return len($self) }
String substring(int start, int end) for python { return $self[$start:$end] }
String strip() for python { return ($self).strip() }
bool startsWith(String other) for python { return ($self).startswith($other) }
bool endsWith(String other) for python { return ($self).endswith($other) }
int find(String other) for python { return ($self).find($other) }
String replaceAll(String from_, String to) for python { return ($self).replace(($from_), ($to)) }
List<String> split(String sep) for python { return ($self).split($sep) }
String join(List<String> parts) for python { return ($self).join($parts) }
String toUpper() for python { return ($self).upper() }
String toLower() for python { return ($self).lower() }

String __add__(String other) for ruby { return $self + $other }
bool __eq__(String other) for ruby { return $self == $other }
int size() for ruby { return $self.size }
String substring(int start, int end) for ruby {
return $self.slice($start, $end - $start)
}
String strip() for ruby { return ($self).strip }
bool startsWith(String other) for ruby { return ($self).start_with?($other) }
bool endsWith(String other) for ruby { return ($self).end_with?($other) }
int find(String other) for ruby { return (($self).index($other) or -1) }
String replaceAll(String from, String to) for ruby { return ($self).gsub(($from), ($to)) }
List<String> split(String sep) for ruby {
return ['', ''] if $self == $sep
result = $self.split($sep)
result = result + [''] if ($self).end_with? $sep
result
}
String join(List<String> parts) for ruby { return ($parts).join($self) }
String toUpper() for ruby { return ($self).upcase }
String toLower() for ruby { return ($self).downcase }

String __add__(String other) for javascript { return $self + $other }
bool __eq__(String other) for javascript { return $self === $other }
int size() for javascript { return $self.length }
String substring(int start, int end) for javascript { return $self.substring($start, $end) }
String strip() for javascript { return ($self).trim() }
bool startsWith(String other) for javascript { return (($self).indexOf($other)===0)}
bool endsWith(String other) for javascript { return (($self).indexOf(($other), ($self).length - ($other).length) !== -1)}
int find(String other) for javascript { return ($self).indexOf($other)}
String replaceAll(String from, String to) for javascript { return ($self).split($from).join($to) }
List<String> split(String sep) for javascript { return ($self).split($sep)}
String join(List<String> parts) for javascript { return ($parts).join($self)}
String toUpper() for javascript { return ($self).toUpperCase()}
String toLower() for javascript { return ($self).toLowerCase()}

Any to_quark_Any();
Scalar to_quark_Scalar();
Expand Down
81 changes: 81 additions & 0 deletions quarkc/test/e2e/primitives.q
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,87 @@ class StringTest {
assertEqual(false, "abc" == "def");
}

void upper_lower() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than growing primitives.q even more, can we put these type-specific tests into separate quark files? Maybe something like bi_string.q (for built-in) or lib_list.q or whatever? Something consistent would be great.

assertEqual("asdf", "AsDf".toLower());
assertEqual("ASDF", "AsDf".toUpper());
}

void strip() {
assertEqual("Abc".strip(), "Abc");
assertEqual("Abc ".strip(), "Abc");
assertEqual(" Abc".strip(), "Abc");
assertEqual(" Abc ".strip(), "Abc");
assertEqual("\t \nAbc\n \t ".strip(), "Abc");

List<String> ws = ["", " ", "\t", "\n", "\r"];
String s = "<--->";
int i = 0;
while (i < ws.size()) {
int j = 0;
while (j < ws.size()) {
assertEqual(s, (ws[i] + s + ws[j]).strip());
j = j + 1;
}
assertEqual("", ws[i].strip());
i = i + 1;
}
}

void join() {
assertEqual("".join([]), "");
assertEqual("++".join([]), "");
assertEqual("".join(["a", "bc"]), "abc");
assertEqual("++".join(["a", "bc", "d"]), "a++bc++d");
}

void split() {
List<String> l = ["a", "c"];
assertEqual("abc".split("b"), l);
l = ["a", "c", "", "d"];
assertEqual("aGOcGOGOd".split("GO"), l);
l = ["abc"];
assertEqual("abc".split("z"), l);
}

void replaceAll() {
assertEqual("abc".replaceAll("bc", "z"), "az");
assertEqual("aGOdGO".replaceAll("GO", "me"), "amedme");
// Make sure we're not somehow using regexs:
assertEqual("a.csc".replaceAll(".c", "z"), "azsc");
}

void endsWith() {
assertEqual("abc".endsWith(""), true);
assertEqual("abc".endsWith("c"), true);
assertEqual("abc".endsWith("bc"), true);
assertEqual("abc".endsWith("abc"), true);
assertEqual("abc".endsWith("abcd"), false);
assertEqual("abc".endsWith("ab"), false);
assertEqual("abc".endsWith("z"), false);
}

void startsWith() {
assertEqual("abc".startsWith(""), true);
assertEqual("abc".startsWith("a"), true);
assertEqual("abc".startsWith("ab"), true);
assertEqual("abc".startsWith("abc"), true);
assertEqual("abc".startsWith("abcd"), false);
assertEqual("abc".startsWith("bc"), false);
assertEqual("abc".startsWith("z"), false);
}

void find() {
assertEqual("Abc".find("z"), -1);
assertEqual("Abc".find(""), 0);
assertEqual("Abc".find("A"), 0);
assertEqual("Abc".find("Ab"), 0);
assertEqual("Abc".find("Abc"), 0);
assertEqual("Abc".find("Abcz"), -1);
assertEqual("Abc".find("zAbc"), -1);
assertEqual("Abc".find("b"), 1);
assertEqual("Abc".find("bc"), 1);
assertEqual("Abc".find("c"), 2);
}
}


Expand Down