Skip to content

Commit

Permalink
Add chr built-in function
Browse files Browse the repository at this point in the history
```
chr(i)
```

This behaves similarly to Python's built-in `chr` function: for a given
integer `i`, it returns a string containing the character whose Unicode
code point is `i`. It is an error to provide an `i` that is not an
integer or falls outside the Unicode code point range.
  • Loading branch information
chrisnovakovic committed Oct 11, 2023
1 parent c97dc5b commit ef94e7e
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 1 deletion.
10 changes: 10 additions & 0 deletions docs/lexicon.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ <h2 class="title-2" id="python-builtins">
- returns the length of <code class="code">x</code>.
</span>
</li>
<li>
<span>
<code class="code"
><span class="fn-name">chr</span><span class="fn-p">(</span
><span class="fn-arg">i</span><span class="fn-p">)</span></code
>
- returns a string containing the character whose Unicode code point
is the integer <code class="code">i</code>.
</span>
</li>
<li>
<span>
<code class="code"
Expand Down
2 changes: 2 additions & 0 deletions rules/builtins.build_defs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def build_rule(name:str, cmd:str|dict='', test_cmd:str|dict='', debug_cmd:str=''
_subrepo:bool=False):
pass

def chr(i:int) -> str:
pass
def len(obj:list|dict|str) -> int:
pass
def enumerate(seq:list):
Expand Down
9 changes: 9 additions & 0 deletions src/parse/asp/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"sync"
"unicode"

"github.com/Masterminds/semver/v3"
"github.com/manifoldco/promptui"
Expand Down Expand Up @@ -47,6 +48,7 @@ func registerBuiltins(s *scope) {
setNativeCode(s, "all", allFunc)
setNativeCode(s, "min", min)
setNativeCode(s, "max", max)
setNativeCode(s, "chr", chr)
setNativeCode(s, "len", lenFunc)
setNativeCode(s, "glob", glob)
setNativeCode(s, "bool", boolType)
Expand Down Expand Up @@ -402,6 +404,13 @@ func objLen(obj pyObject) pyInt {
panic("object of type " + obj.Type() + " has no len()")
}

func chr(s *scope, args []pyObject) pyObject {
i, isInt := args[0].(pyInt)
s.Assert(isInt, "Argument i must be an integer, not %s", args[0].Type())
s.Assert(i >= 0 && i <= unicode.MaxRune, "Argument i must be within the Unicode code point range")
return pyString(i)

Check failure on line 411 in src/parse/asp/builtins.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from pyInt (int) to pyString (string) yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?) (govet)
}

func isinstance(s *scope, args []pyObject) pyObject {
obj := args[0]
typesArg := args[1]
Expand Down
23 changes: 23 additions & 0 deletions src/parse/asp/interpreter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,29 @@ func TestMax(t *testing.T) {
})
}

func TestChr(t *testing.T) {
t.Run("OK", func(t *testing.T) {
s, err := parseFile("src/parse/asp/test_data/interpreter/chr.build")
assert.NoError(t, err)
assert.EqualValues(t, pyString("\x00"), s.Lookup("null"))
assert.EqualValues(t, pyString("a"), s.Lookup("a"))
assert.EqualValues(t, pyString("€"), s.Lookup("euro"))
assert.EqualValues(t, pyString("\U0010FFFF"), s.Lookup("maximum"))
})
t.Run("Wrong parameter type", func(t *testing.T) {
_, err := parseFile("src/parse/asp/test_data/interpreter/chr_wrong_type.build")
assert.ErrorContains(t, err, "Invalid type for argument i to chr; expected int, was str")
})
t.Run("Parameter out of bounds (too low)", func(t *testing.T) {
_, err := parseFile("src/parse/asp/test_data/interpreter/chr_bounds_low.build")
assert.ErrorContains(t, err, "Argument i must be within the Unicode code point range")
})
t.Run("Parameter out of bounds (too high)", func(t *testing.T) {
_, err := parseFile("src/parse/asp/test_data/interpreter/chr_bounds_high.build")
assert.ErrorContains(t, err, "Argument i must be within the Unicode code point range")
})
}

func TestIsSemver(t *testing.T) {
t.Run("OK", func(t *testing.T) {
s, err := parseFile("src/parse/asp/test_data/interpreter/is_semver.build")
Expand Down
4 changes: 4 additions & 0 deletions src/parse/asp/test_data/interpreter/chr.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
null = chr(0)
a = chr(97)
euro = chr(8364)
maximum = chr(1114111)
1 change: 1 addition & 0 deletions src/parse/asp/test_data/interpreter/chr_bounds_high.build
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = chr(1114112)
1 change: 1 addition & 0 deletions src/parse/asp/test_data/interpreter/chr_bounds_low.build
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = chr(-1)
1 change: 1 addition & 0 deletions src/parse/asp/test_data/interpreter/chr_wrong_type.build
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = chr("x")
2 changes: 1 addition & 1 deletion third_party/go/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ go_repo(

go_repo(
module = "github.com/stretchr/testify",
version = "v1.7.0",
version = "v1.8.4",
)

go_repo(
Expand Down

0 comments on commit ef94e7e

Please sign in to comment.