From cab0cc887e2f099bc797a0ffe948438bdb2f0ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Barzowski?= Date: Tue, 12 Sep 2017 14:52:00 -0400 Subject: [PATCH] std.codepoint, std.char + a bunch of tests --- builtins.go | 31 ++++++++++++++++++++ testdata/builtinChar.golden | 1 + testdata/builtinChar.input | 1 + testdata/builtinChar2.golden | 1 + testdata/builtinChar2.input | 1 + testdata/builtinChar3.golden | 1 + testdata/builtinChar3.input | 1 + testdata/builtinChar4.golden | 1 + testdata/builtinChar4.input | 1 + testdata/builtinChar5.golden | 1 + testdata/builtinChar5.input | 2 ++ testdata/builtinChar6.golden | 1 + testdata/builtinChar6.input | 2 ++ testdata/error_hexnumber.golden | 1 + testdata/error_hexnumber.input | 1 + testdata/number_leading_zero.golden | 1 + testdata/number_leading_zero.input | 1 + testdata/std.codepoint.golden | 1 + testdata/std.codepoint.input | 1 + testdata/std.codepoint2.golden | 1 + testdata/std.codepoint2.input | 1 + testdata/std.codepoint3.golden | 1 + testdata/std.codepoint3.input | 1 + testdata/std.codepoint4.golden | 1 + testdata/std.codepoint4.input | 1 + testdata/std.codepoint5.golden | 1 + testdata/std.codepoint5.input | 1 + testdata/std.codepoint6.golden | 1 + testdata/std.codepoint6.input | 1 + testdata/std.codepoint7.golden | 1 + testdata/std.codepoint7.input | 2 ++ testdata/type_builtin_function.golden | 1 + testdata/type_builtin_function.input | 1 + testdata/type_error.golden | 1 + testdata/type_error.input | 1 + testdata/{type.golden => type_number.golden} | 0 testdata/{type.input => type_number.input} | 0 37 files changed, 68 insertions(+) create mode 100644 testdata/builtinChar.golden create mode 100644 testdata/builtinChar.input create mode 100644 testdata/builtinChar2.golden create mode 100644 testdata/builtinChar2.input create mode 100644 testdata/builtinChar3.golden create mode 100644 testdata/builtinChar3.input create mode 100644 testdata/builtinChar4.golden create mode 100644 testdata/builtinChar4.input create mode 100644 testdata/builtinChar5.golden create mode 100644 testdata/builtinChar5.input create mode 100644 testdata/builtinChar6.golden create mode 100644 testdata/builtinChar6.input create mode 100644 testdata/error_hexnumber.golden create mode 100644 testdata/error_hexnumber.input create mode 100644 testdata/number_leading_zero.golden create mode 100644 testdata/number_leading_zero.input create mode 100644 testdata/std.codepoint.golden create mode 100644 testdata/std.codepoint.input create mode 100644 testdata/std.codepoint2.golden create mode 100644 testdata/std.codepoint2.input create mode 100644 testdata/std.codepoint3.golden create mode 100644 testdata/std.codepoint3.input create mode 100644 testdata/std.codepoint4.golden create mode 100644 testdata/std.codepoint4.input create mode 100644 testdata/std.codepoint5.golden create mode 100644 testdata/std.codepoint5.input create mode 100644 testdata/std.codepoint6.golden create mode 100644 testdata/std.codepoint6.input create mode 100644 testdata/std.codepoint7.golden create mode 100644 testdata/std.codepoint7.input create mode 100644 testdata/type_builtin_function.golden create mode 100644 testdata/type_builtin_function.input create mode 100644 testdata/type_error.golden create mode 100644 testdata/type_error.input rename testdata/{type.golden => type_number.golden} (100%) rename testdata/{type.input => type_number.input} (100%) diff --git a/builtins.go b/builtins.go index bee1893..7065d05 100644 --- a/builtins.go +++ b/builtins.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/md5" "encoding/hex" + "fmt" "math" "sort" @@ -384,6 +385,34 @@ func builtinMd5(e *evaluator, xp potentialValue) (value, error) { return makeValueString(hex.EncodeToString(hash[:])), nil } +// Maximum allowed unicode codepoint +// https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology +const codepointMax = 0x10FFFF + +func builtinChar(e *evaluator, xp potentialValue) (value, error) { + x, err := e.evaluateNumber(xp) + if err != nil { + return nil, err + } + if x.value > codepointMax { + return nil, e.Error(fmt.Sprintf("Invalid unicode codepoint, got %v", x.value)) + } else if x.value < 0 { + return nil, e.Error(fmt.Sprintf("Codepoints must be >= 0, got %v", x.value)) + } + return makeValueString(string(rune(x.value))), nil +} + +func builtinCodepoint(e *evaluator, xp potentialValue) (value, error) { + x, err := e.evaluateString(xp) + if err != nil { + return nil, err + } + if x.length() != 1 { + return nil, e.Error(fmt.Sprintf("codepoint takes a string of length 1, got length %v", x.length())) + } + return makeValueNumber(float64(x.value[0])), nil +} + func makeDoubleCheck(e *evaluator, x float64) (value, error) { if math.IsNaN(x) { return nil, e.Error("Not a number") @@ -612,6 +641,8 @@ var funcBuiltins = map[string]evalCallable{ "objectFieldsEx": &BinaryBuiltin{name: "objectFields", function: builtinObjectFieldsEx, parameters: ast.Identifiers{"obj", "hidden"}}, "objectHasEx": &TernaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, parameters: ast.Identifiers{"obj", "fname", "hidden"}}, "type": &UnaryBuiltin{name: "type", function: builtinType, parameters: ast.Identifiers{"x"}}, + "char": &UnaryBuiltin{name: "char", function: builtinChar, parameters: ast.Identifiers{"x"}}, + "codepoint": &UnaryBuiltin{name: "codepoint", function: builtinCodepoint, parameters: ast.Identifiers{"x"}}, "ceil": &UnaryBuiltin{name: "ceil", function: builtinCeil, parameters: ast.Identifiers{"x"}}, "floor": &UnaryBuiltin{name: "floor", function: builtinFloor, parameters: ast.Identifiers{"x"}}, "sqrt": &UnaryBuiltin{name: "sqrt", function: builtinSqrt, parameters: ast.Identifiers{"x"}}, diff --git a/testdata/builtinChar.golden b/testdata/builtinChar.golden new file mode 100644 index 0000000..d478a3d --- /dev/null +++ b/testdata/builtinChar.golden @@ -0,0 +1 @@ +"A" diff --git a/testdata/builtinChar.input b/testdata/builtinChar.input new file mode 100644 index 0000000..53d6f35 --- /dev/null +++ b/testdata/builtinChar.input @@ -0,0 +1 @@ +std.char(65) diff --git a/testdata/builtinChar2.golden b/testdata/builtinChar2.golden new file mode 100644 index 0000000..09c5044 --- /dev/null +++ b/testdata/builtinChar2.golden @@ -0,0 +1 @@ +"\u0000" diff --git a/testdata/builtinChar2.input b/testdata/builtinChar2.input new file mode 100644 index 0000000..fa8113f --- /dev/null +++ b/testdata/builtinChar2.input @@ -0,0 +1 @@ +std.char(0) diff --git a/testdata/builtinChar3.golden b/testdata/builtinChar3.golden new file mode 100644 index 0000000..12c2801 --- /dev/null +++ b/testdata/builtinChar3.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Codepoints must be >= 0, got -1 diff --git a/testdata/builtinChar3.input b/testdata/builtinChar3.input new file mode 100644 index 0000000..e506045 --- /dev/null +++ b/testdata/builtinChar3.input @@ -0,0 +1 @@ +std.char(-1) diff --git a/testdata/builtinChar4.golden b/testdata/builtinChar4.golden new file mode 100644 index 0000000..90b74f3 --- /dev/null +++ b/testdata/builtinChar4.golden @@ -0,0 +1 @@ +"*" diff --git a/testdata/builtinChar4.input b/testdata/builtinChar4.input new file mode 100644 index 0000000..fa98a4a --- /dev/null +++ b/testdata/builtinChar4.input @@ -0,0 +1 @@ +std.char(42) diff --git a/testdata/builtinChar5.golden b/testdata/builtinChar5.golden new file mode 100644 index 0000000..130e096 --- /dev/null +++ b/testdata/builtinChar5.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Invalid unicode codepoint, got 1.114112e+06 diff --git a/testdata/builtinChar5.input b/testdata/builtinChar5.input new file mode 100644 index 0000000..e97c414 --- /dev/null +++ b/testdata/builtinChar5.input @@ -0,0 +1,2 @@ +// too big +std.char(1114112) diff --git a/testdata/builtinChar6.golden b/testdata/builtinChar6.golden new file mode 100644 index 0000000..3ac6a23 --- /dev/null +++ b/testdata/builtinChar6.golden @@ -0,0 +1 @@ +"􏿿" diff --git a/testdata/builtinChar6.input b/testdata/builtinChar6.input new file mode 100644 index 0000000..8af66cb --- /dev/null +++ b/testdata/builtinChar6.input @@ -0,0 +1,2 @@ +// biggest allowed +std.char(1114111) diff --git a/testdata/error_hexnumber.golden b/testdata/error_hexnumber.golden new file mode 100644 index 0000000..5df6103 --- /dev/null +++ b/testdata/error_hexnumber.golden @@ -0,0 +1 @@ +testdata/error_hexnumber:1:2-5 Did not expect: (IDENTIFIER, "x42") diff --git a/testdata/error_hexnumber.input b/testdata/error_hexnumber.input new file mode 100644 index 0000000..9bc1b8c --- /dev/null +++ b/testdata/error_hexnumber.input @@ -0,0 +1 @@ +0x42 diff --git a/testdata/number_leading_zero.golden b/testdata/number_leading_zero.golden new file mode 100644 index 0000000..8abcd7a --- /dev/null +++ b/testdata/number_leading_zero.golden @@ -0,0 +1 @@ +testdata/number_leading_zero:1:2-4 Did not expect: (NUMBER, "42") diff --git a/testdata/number_leading_zero.input b/testdata/number_leading_zero.input new file mode 100644 index 0000000..f0b7b2e --- /dev/null +++ b/testdata/number_leading_zero.input @@ -0,0 +1 @@ +042 diff --git a/testdata/std.codepoint.golden b/testdata/std.codepoint.golden new file mode 100644 index 0000000..1479e19 --- /dev/null +++ b/testdata/std.codepoint.golden @@ -0,0 +1 @@ +65 diff --git a/testdata/std.codepoint.input b/testdata/std.codepoint.input new file mode 100644 index 0000000..1bd78d7 --- /dev/null +++ b/testdata/std.codepoint.input @@ -0,0 +1 @@ +std.codepoint('A') diff --git a/testdata/std.codepoint2.golden b/testdata/std.codepoint2.golden new file mode 100644 index 0000000..573541a --- /dev/null +++ b/testdata/std.codepoint2.golden @@ -0,0 +1 @@ +0 diff --git a/testdata/std.codepoint2.input b/testdata/std.codepoint2.input new file mode 100644 index 0000000..eb6a95c --- /dev/null +++ b/testdata/std.codepoint2.input @@ -0,0 +1 @@ +std.codepoint("\u0000") diff --git a/testdata/std.codepoint3.golden b/testdata/std.codepoint3.golden new file mode 100644 index 0000000..a5a70e0 --- /dev/null +++ b/testdata/std.codepoint3.golden @@ -0,0 +1 @@ +RUNTIME ERROR: codepoint takes a string of length 1, got length 2 diff --git a/testdata/std.codepoint3.input b/testdata/std.codepoint3.input new file mode 100644 index 0000000..9625f52 --- /dev/null +++ b/testdata/std.codepoint3.input @@ -0,0 +1 @@ +std.codepoint("aa") diff --git a/testdata/std.codepoint4.golden b/testdata/std.codepoint4.golden new file mode 100644 index 0000000..4fc233b --- /dev/null +++ b/testdata/std.codepoint4.golden @@ -0,0 +1 @@ +261 diff --git a/testdata/std.codepoint4.input b/testdata/std.codepoint4.input new file mode 100644 index 0000000..2e491b0 --- /dev/null +++ b/testdata/std.codepoint4.input @@ -0,0 +1 @@ +std.codepoint("ą") diff --git a/testdata/std.codepoint5.golden b/testdata/std.codepoint5.golden new file mode 100644 index 0000000..e81ba05 --- /dev/null +++ b/testdata/std.codepoint5.golden @@ -0,0 +1 @@ +21488 diff --git a/testdata/std.codepoint5.input b/testdata/std.codepoint5.input new file mode 100644 index 0000000..78b8b96 --- /dev/null +++ b/testdata/std.codepoint5.input @@ -0,0 +1 @@ +std.codepoint("台") diff --git a/testdata/std.codepoint6.golden b/testdata/std.codepoint6.golden new file mode 100644 index 0000000..8eca754 --- /dev/null +++ b/testdata/std.codepoint6.golden @@ -0,0 +1 @@ +RUNTIME ERROR: codepoint takes a string of length 1, got length 0 diff --git a/testdata/std.codepoint6.input b/testdata/std.codepoint6.input new file mode 100644 index 0000000..02091fd --- /dev/null +++ b/testdata/std.codepoint6.input @@ -0,0 +1 @@ +std.codepoint("") diff --git a/testdata/std.codepoint7.golden b/testdata/std.codepoint7.golden new file mode 100644 index 0000000..a5a70e0 --- /dev/null +++ b/testdata/std.codepoint7.golden @@ -0,0 +1 @@ +RUNTIME ERROR: codepoint takes a string of length 1, got length 2 diff --git a/testdata/std.codepoint7.input b/testdata/std.codepoint7.input new file mode 100644 index 0000000..5101273 --- /dev/null +++ b/testdata/std.codepoint7.input @@ -0,0 +1,2 @@ +// Two codepoint version using combining ogonek u0328 +std.codepoint("ą") diff --git a/testdata/type_builtin_function.golden b/testdata/type_builtin_function.golden new file mode 100644 index 0000000..f45c029 --- /dev/null +++ b/testdata/type_builtin_function.golden @@ -0,0 +1 @@ +"function" diff --git a/testdata/type_builtin_function.input b/testdata/type_builtin_function.input new file mode 100644 index 0000000..bafe1a0 --- /dev/null +++ b/testdata/type_builtin_function.input @@ -0,0 +1 @@ +std.type(std.type) diff --git a/testdata/type_error.golden b/testdata/type_error.golden new file mode 100644 index 0000000..7bc34d8 --- /dev/null +++ b/testdata/type_error.golden @@ -0,0 +1 @@ +RUNTIME ERROR: xxx diff --git a/testdata/type_error.input b/testdata/type_error.input new file mode 100644 index 0000000..e5e9722 --- /dev/null +++ b/testdata/type_error.input @@ -0,0 +1 @@ +std.type(error "xxx") diff --git a/testdata/type.golden b/testdata/type_number.golden similarity index 100% rename from testdata/type.golden rename to testdata/type_number.golden diff --git a/testdata/type.input b/testdata/type_number.input similarity index 100% rename from testdata/type.input rename to testdata/type_number.input