Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
fec7b1b
chore(nimble): requires "nim < 0.20"
litlighilit Jul 11, 2025
a8d5659
fix(nimc): nnkTupleConstr used to be nnkPar
litlighilit Jul 10, 2025
c69dedd
fix(nimc): get rid of `Error: illegal capture 'selfNoCast' ...
litlighilit Jul 11, 2025
2b5efb6
fix(nimc): type mismatch in Python/symtable
litlighilit Jul 11, 2025
00e3909
fix(nimc): when gen repr for exceptions: `Error: got prototype: OpenS…
litlighilit Jul 11, 2025
dab5900
fix(nimc): downcast in tuple now must be explicit?
litlighilit Jul 11, 2025
53253bc
fix(nimc): `Error: cannot bind another '=destroy' to: PyCodeObject:Ob…
litlighilit Jul 11, 2025
b645cb6
fix(nimc): get rid of `Error: illegal capture 'args'... followup HEAD~5
litlighilit Jul 11, 2025
43fc39d
fix(rt): grammar:newGrammarNode: assignment to discriminant changes o…
litlighilit Jul 11, 2025
e6bcaf3
fix(rt): lexer:newTokenNode(followup HEAD^)
litlighilit Jul 11, 2025
296461a
fix(rt): grammar:genExpsilonSet: the length of the HashSet changed wh…
litlighilit Jul 11, 2025
a7e26a9
fix(rt): multimethods is off since 0.20
litlighilit Jul 11, 2025
347937c
chore(nimble): requires "nim >= 1.6.14"
litlighilit Jul 11, 2025
472ac5f
chore(gitignore): /bin/
litlighilit Jul 11, 2025
5a90c4a
fix(warning): [Deprecated] in system/stdlib:...
litlighilit Jul 11, 2025
510ca46
fix(warning): [Deprecated] in pkg/regex: re,find shall be suffixed by…
litlighilit Jul 11, 2025
0d6c748
fix(warning): [UnusedImport] of stdlib; and a dup import
litlighilit Jul 11, 2025
26b39ac
fix(warning): [UnusedImport] of inner libs
litlighilit Jul 11, 2025
7c382d7
fix(nimc/js): no system.outOfMemHook on JS
litlighilit Jul 11, 2025
aa489e3
chore(nimble): task test: support passing arg for subTest
litlighilit Jul 11, 2025
d632b8f
bump-version: 0.1.1
litlighilit Jul 11, 2025
4c7318e
fixup: repl now prints updated version; dep(!cligen)
litlighilit Jul 11, 2025
344134f
feat(cli): -V,--version
litlighilit Jul 11, 2025
d8c06d5
chore(nimble): compile target now named npython over python
litlighilit Jul 11, 2025
1984a25
fixup: HEAD~2: -VVV ('-V'>2) now means -VV than error
litlighilit Jul 11, 2025
6f8e056
feat(cli): -c
litlighilit Jul 11, 2025
2093ab9
feat(cli): -q; fix(py): repl now print platform
litlighilit Jul 11, 2025
ff73790
doc(readme): update "How to use" & "Drawbacks"
litlighilit Jul 11, 2025
28059a9
fixup
litlighilit Jul 11, 2025
54cd9c7
fix(nimc): CC:clang not compile Objects/exceptions.nim:`new*Error`
litlighilit Jul 12, 2025
ba0244a
fixup: 6f8e0566fe95949: -c not init py
litlighilit Jul 13, 2025
e3bce62
refine(dep): use pkg/regex iff -d:npythonUseRegex;std/nre iff -d:npyt…
litlighilit Jul 13, 2025
ce97b39
impr(lexer): purge usage of re
litlighilit Jul 13, 2025
660a10d
fix(list.remove): `LockError: Read failed because object is been writ…
litlighilit Jul 13, 2025
4694f65
feat(tuple): `__contains__`,index,count;feat(list): `__eq__`
litlighilit Jul 13, 2025
5d04612
feat(tuple,list): __add__; list.extend
litlighilit Jul 13, 2025
19c58dd
feat(str): fallback to call `__repr__` if no `__str__`
litlighilit Jul 13, 2025
d377f1b
fix(ast): (1,) was regarded as 1 over tuple
litlighilit Jul 13, 2025
9125f01
fix(tuple): repr((1,)) was "(1)"
litlighilit Jul 13, 2025
6a470f6
fixup! feat(tuple,list): __add__; list.extend
litlighilit Jul 13, 2025
7dfaad4
feat(set): new (some methods not impl yet); ...
litlighilit Jul 13, 2025
1c58f02
feat(inner): dedup iterable loop as pyForIn
litlighilit Jul 13, 2025
1e18879
feat(set): all method (not test)
litlighilit Jul 13, 2025
2208c7f
feat(syntax/indent): allow any number of spaces (tab as 8 spaces)
litlighilit Jul 14, 2025
3a5b72a
fix(int): -1+10 = -9
litlighilit Jul 14, 2025
0c52a12
fix(int): 1-10 = 8589934583
litlighilit Jul 14, 2025
7fc0524
impr(int) `$` faster
litlighilit Jul 14, 2025
7787205
feat(int,float): support: a//b for int where b is big; `%` for int,float
litlighilit Jul 14, 2025
d7fa598
feat(float): divmod (inner)
litlighilit Jul 14, 2025
14dc7a3
fix(py): repr for self-containing dict,list was "..."
litlighilit Jul 14, 2025
1be7e52
fix(py): type name was captial e.g. Set
litlighilit Jul 14, 2025
2698008
fix(py): repr(set()) was "{}"
litlighilit Jul 14, 2025
1d5a0c8
fix(js): AstNodeBase.hash crash bc cast to int from ref
litlighilit Jul 15, 2025
e95c3fb
fix(js): `log` func may be of karax's
litlighilit Jul 15, 2025
73b3c0e
fixup(js): findExe not work CT when JS
litlighilit Jul 15, 2025
98a85c8
fix(js): make lefecycle.pyInit init pyConfig, too (like in C)
litlighilit Jul 15, 2025
3da36ad
feat(js): nodejs run .py file
litlighilit Jul 15, 2025
0054380
feat(js): nodejs repl
litlighilit Jul 15, 2025
b7b9886
chore(nimble): allow pass cmd args for buildJs task
litlighilit Jul 15, 2025
682eb2f
feat(js): sup deno; sup -d:jsAlert to gen a prompt&alert repl; sup -d…
litlighilit Jul 16, 2025
86a6442
chore(nimble): buildKarax
litlighilit Jul 16, 2025
9affd0c
refact(karaxpython): split from jspython
litlighilit Jul 16, 2025
c41c3b5
fix(js): handle: spaces in browser's contenteditable may become U+00A0
litlighilit Jul 16, 2025
af9986a
feat(js): browser (karax) repl
litlighilit Jul 16, 2025
c50a8fc
refine: fixup: use pre over p for line showing, simplfying many things
litlighilit Jul 16, 2025
1cfd3d4
chore(nimble): breaks: `chore(nimble): buildKarax`, npython is now ap…
litlighilit Jul 16, 2025
9bbec5a
feat(mykarun): --includeJs for one-file html
litlighilit Jul 16, 2025
df15dd0
chore(ci): playground
litlighilit Jul 16, 2025
be12b79
fixup: need to create deploy-dir
litlighilit Jul 16, 2025
b971429
impr(karaxpython): add simple info line about repo url
litlighilit Jul 16, 2025
e22d979
doc(readme): update url of github & online playground; detailed "How …
litlighilit Jul 16, 2025
7c15c29
feat(karaxpython/ui): edit line is focused on user entering page
litlighilit Jul 17, 2025
e38f9da
feat(karaxpython/ui): history (bug: cursor not to end on restoring)
litlighilit Jul 17, 2025
8a959cd
fixup: bug: cursor not to end on restoring
litlighilit Jul 17, 2025
8fdea03
fixup: the last incomplete input cannot be restored
litlighilit Jul 17, 2025
c34fa87
feat(magic): iXX (e.g. `__iadd__`)
litlighilit Jul 17, 2025
b431380
feat(builtins): NotImplemented
litlighilit Jul 17, 2025
eed6d9c
feat(augassign): impl `a.__iXX__(b)` fallback to `a=a.__XX__(b)`
litlighilit Jul 17, 2025
fe923ef
fix(lexer): `""` and `''` crash lexer (TODO: multiline string)
litlighilit Jul 17, 2025
35a0f3a
feat(implMagic): for binary magic allow typed params
litlighilit Jul 17, 2025
75cc8ce
feat(str): `__add__`
litlighilit Jul 17, 2025
d02caf5
feat(karaxpython/ui): wrap line if overflow
litlighilit Jul 18, 2025
bcb7d9e
impr(ast): parse float/int and string were too slow!
litlighilit Jul 18, 2025
511e0f2
fixup(NotImplemented): `type(NotImplemented)() is not NotImplemented`
litlighilit Jul 18, 2025
b358539
feat(builtin): Ellipsis (ast syntax `...` is sup too)
litlighilit Jul 18, 2025
fcfe141
fix(windows): lexer init not run; buildinfo contains newline
litlighilit Jul 18, 2025
99c34b4
fixup! feat(implMagic): for binary magic allow typed params
litlighilit Jul 18, 2025
5f8bad7
fix(Parser.grammar): not correct err msg
litlighilit Jul 19, 2025
7434a44
feat(versionInfo): add PyMajor,PyMinor,PyPatch
litlighilit Jul 21, 2025
89823ce
refact(lexer): mv types to lexerTypes
litlighilit Jul 21, 2025
8ee5bfb
feat(warnings): nim api: warnExplicit (not complete, a simpler impl)
litlighilit Jul 21, 2025
7c70439
feat(Utils): translateEscape from nimpylib@c0a6f744ca9c7787d38e78ecae…
litlighilit Jul 21, 2025
06ab264
feat(parser/strlit),fix(py): add decode_unicode_with_escapes, escape …
litlighilit Jul 21, 2025
8bd66ba
feat(str): UCS-4 or UCS-1 based over only UCS-1(ascii)
litlighilit Jul 21, 2025
94931af
feat(Utils): rangeLen from nimpylib@aca732bcf09561a6ef3a6d4957af55ec8…
litlighilit Jul 21, 2025
30263ee
refine(slice): getSliceItems used ptr over var
litlighilit Jul 21, 2025
e3bf556
fix(py): [1][0:1] raised IndexError
litlighilit Jul 21, 2025
0039346
feat(str): sequence methods and .find
litlighilit Jul 21, 2025
ea5a2cd
feat(syntax): DeleteSubScr op (`__delitem__`)
litlighilit Jul 21, 2025
dc67a3e
feat(list): setitem,deliem accept slice
litlighilit Jul 21, 2025
c8964e0
fix(None): `type(None)() is not None`; no `__repr__` (followup 511e0f2)
litlighilit Jul 21, 2025
4aea40e
feat(slice): .indices
litlighilit Jul 21, 2025
4866a19
feat(builtins): slice
litlighilit Jul 21, 2025
045eb6e
fix(bool): type(bool)() is not None (followup 511e0f2); bool [] is True
litlighilit Jul 22, 2025
33ecc77
feat(builtins): bool; fix(py): neval regarded user-define instance as…
litlighilit Jul 22, 2025
ca49d97
fixup! feat(warnings): nim api: warnExplicit (not complete, a simpler…
litlighilit Jul 22, 2025
4b28a22
feat(syntax): multi-targets in del_stmt (e.g. `del ls[0], ls[1]`)
litlighilit Jul 22, 2025
2be4169
feat(builtins): dict methods except keys,values,fromkeys,update; `__d…
litlighilit Jul 22, 2025
dfe28ce
feat(syntax): DeleteAttr op (`__delattr__`)
litlighilit Jul 22, 2025
c1c9801
fix(py): hash(<tuple>) was id-based over content-based
litlighilit Jul 22, 2025
be0b272
fix(py): hash worked for dict,list,set
litlighilit Jul 22, 2025
481d387
feat(iterobject): NimIteratorIter
litlighilit Jul 22, 2025
4242ad2
fix(py): frozenset repr was the same as set's
litlighilit Jul 22, 2025
ff768cb
feat(builtins): next
litlighilit Jul 22, 2025
cca93bc
feat(inner/pyobject): declarePyType accepts custom typeName
litlighilit Jul 22, 2025
889cca6
fix(py): exceptions type names was like "stopitererror"
litlighilit Jul 22, 2025
da03c48
feat(builtins),fix(py): ren as Exception, StopIteration
litlighilit Jul 22, 2025
af6b3d1
feat(inner/exceptions): obj.isExceptionOf(ExceptionToken)
litlighilit Jul 22, 2025
1086066
feat(builtins): getattr, setattr, delattr
litlighilit Jul 22, 2025
c1ea5b2
feat(inner): items, `[]` for list,tuple object
litlighilit Jul 22, 2025
8df80d3
fix(py): `dict.__eq__` not content-based;;dict no tpToken
litlighilit Jul 22, 2025
7457d84
refact,feat(dict): ren dictobject.keys keysList;impl values,items,keys
litlighilit Jul 22, 2025
d5e93e2
fix(py): list(dict) was on .keys() over .items()
litlighilit Jul 22, 2025
25b128f
feat(dict): all meth except fromkeys,popitem; fix(py): dict() accepte…
litlighilit Jul 22, 2025
120063b
refine(opt): followup 8bd66ba1772e038503fe03c4a3e82acdd812fd65
litlighilit Jul 22, 2025
edddd9a
refine(cpython): rm unused bool result
litlighilit Jul 23, 2025
6ab9a6c
fix(inner): $codeobject not work for `OpCode.Delete*`
litlighilit Jul 23, 2025
7c3d9be
feat(syntax/del_name): (not work for repl)
litlighilit Jul 23, 2025
288f85d
feat(syntax/except_with_name): (wrong scope in some cases)
litlighilit Jul 27, 2025
97bae3e
feat(syntax/finally): try: ... finally: ...
litlighilit Jul 29, 2025
8a80369
fix(nimc): not compile when -d:debug
litlighilit Jul 29, 2025
06960be
feat(syntax/strlit): sup u/r prefix
litlighilit Jul 29, 2025
97daab1
wip(gram): add BYTES token
litlighilit Jul 29, 2025
7aa5d62
feat(bytes): bltins, add `__bytes__` magic (almost no magic,method impl)
litlighilit Jul 29, 2025
3b4ad37
feat(errors): ArithmeticError, OverflowError
litlighilit Jul 29, 2025
4d91968
fix(py): replace toInt with toIntOrRetOF to handle overflow; impl PyN…
litlighilit Jul 29, 2025
9bfd07e
feat(syntax): sup b/B prefix
litlighilit Jul 29, 2025
30a1f16
feat(bytes): `__new__`
litlighilit Jul 29, 2025
a63b9cc
break(bytearray): internally use seq[char] over string
litlighilit Jul 30, 2025
c7301aa
impr(iterobject): pyForIn `return` PyBaseErrorObject over PyObject
litlighilit Jul 30, 2025
252979e
feat(builtins): `bytearray.__init__`
litlighilit Jul 30, 2025
7213b8a
feat(inner): followup 00393460da2f3048579: sup stop arg for Utils/`se…
litlighilit Jul 30, 2025
70bd0a7
feat(inner): abstract: add helpers: `numAs*OrE`, `*OptArgAt`
litlighilit Jul 30, 2025
c44dbc1
feat(inner): pyobject: checkTypeOrRetTE, castTypeOrRetTE
litlighilit Jul 30, 2025
ba0f77c
feat(builtins): str: sup start, end param for index,count,find
litlighilit Jul 30, 2025
cd958d7
refact(tuple): exp genGetItem, rm unused param `newPyNameSimple` of `…
litlighilit Jul 30, 2025
a4bf86d
feat(builtins/sequence): sup magic iadd,mul,imul
litlighilit Jul 30, 2025
07044a2
feat(builtins/sequence): sup method reverse
litlighilit Jul 30, 2025
546558a
feat(builtins): bytes/bytearray: impl at least the same methods as tu…
litlighilit Jul 30, 2025
454eefe
fix(builtins/print): default sep used '\n' over ' '
litlighilit Jul 30, 2025
0c8930d
fix(augassign): `**=`,`//=` SyntaxError; `*=`,`%=` NotImplementedError
litlighilit Jul 31, 2025
c2f4335
feat(syntax/import_from): sup `from x import a[, ...]`
litlighilit Jul 31, 2025
a5fd64c
feat(syntax/import): sup `as` (alias), multi import in one stmt
litlighilit Jul 31, 2025
f9732f5
feat(inner): exceptions: add errorIfNot,retIfExc
litlighilit Aug 3, 2025
7d4be97
fix: PyObject_IsTrue carshed when shall raise TypeError
litlighilit Aug 3, 2025
3708eb9
fix(py): exceptions: no LookupError, no attrs
litlighilit Aug 5, 2025
03afe2e
fix(py): printTb was to stdout, all args was printed
litlighilit Aug 5, 2025
cd04936
fix(py): exceptions: `__repr__` returns `xxError: ...`
litlighilit Aug 5, 2025
8e2722e
impr(opt): faster dir
litlighilit Aug 5, 2025
816bb58
fix(py): missing exception type when lookup dict, elem's `__hash__`, …
litlighilit Aug 6, 2025
15efcb8
impr(opt): use withValue over `hasKey` and `[]`
litlighilit Aug 6, 2025
e3f23a3
fixup(4c7318ed65fc3f56): prepare for nim-lang/Nim#25092
litlighilit Aug 9, 2025
3e1f4a9
fix(py): repr(obj) missing "object" before "at"
litlighilit Aug 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/playground.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: playground-deploy

# yamllint disable-line rule:truthy
on:
push:
branches:
- master
tags:
- v*.*
workflow_dispatch:

env:
nim-version: 'stable'
git-repo-url: https://github.com/${{ github.repository }}
deploy-dir: .gh-pages
jobs:
docs:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Cache nimble
id: cache-nimble
uses: actions/cache@v4
with:
path: ~/.nimble
key: ${{ runner.os }}-nimble
- uses: jiro4989/setup-nim-action@v1
with:
nim-version: ${{ env.nim-version }}
- name: install karax
run: nimble install karax
- name: buildKarax
run: |
nimble buildKarax \
-d:homepage="${{ github.event.repository.homepage }}" -d:gitRepoUrl="${{ env.git-repo-url }}" \
-d:release --opt:size --includeJs \
--htmlName=index
- name: "CNAME"
run: mkdir ${{ env.deploy-dir }} || true
- name: mv to deploy dir
run: mv index.html ${{ env.deploy-dir }}/index.html
- name: create deploy-dir if needed
run: |
cname=$(echo ${{ github.event.repository.homepage }} | grep -oP 'https?://\K[^/]+')
prefix="play."
# py: if not cname.startswith(prefix)
# bash: if [[ "${cname}" != $prefix* ]]
if [ ${cname##$prefix} = $cname ]; then
cname="${prefix}${cname}"
fi
echo -n $cname > ${{ env.deploy-dir }}/CNAME
# We must re-build CNAME as we use 'peaceiris/actions-gh-pages@v4',
# where the old dir (including CNAME) will be purged.
- name: Deploy documents
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ${{ env.deploy-dir }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ trash/
./Objects/test.nim

__pycache__/
/bin/
/app.html
/app.js
/npython.html
/npython.js
55 changes: 55 additions & 0 deletions Modules/getbuildinfo.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@


when NimMajor > 1:
from std/paths import `/../`, Path, parentDir
template `/../`(a, b: string): untyped = string(Path(a) /../ Path b)
template parentDir(a: string): untyped = string(Path(a).parentDir)
else:
from std/os import `/../`, parentDir
import ./os_findExe_patch
from std/strutils import stripLineEnd

## see CPython/configure.ac

const gitExe{.strdefine: "git".} = findExe("git")
const git = (exe: gitExe)
when git.exe == "":
template exec(git; sub: string): string = ""
else:
const srcdir_git = currentSourcePath().parentDir /../ ".git"
template exec(git: typeof(git); sub: string): string =
bind srcdir_git
let res = gorgeEx(git.exe & " --git-dir " & srcdir_git & " " & sub)
assert res.exitCode == 0, res.output
var outp = res.output
outp.stripLineEnd
outp

const
version = git.exec"rev-parse --short HEAD"
tag = git.exec"describe --all --always --dirty"
branch = git.exec"name-rev --name-only HEAD"

proc gitidentifier*: string =
result = tag
if result != "" and result != "undefined":
return
result = branch


proc getBuildInfo: string{.compileTime.} =
let revision = version
result = gitidentifier()
if revision != "":
result.add ':'
result.add revision

result.add ", "

#result.add &"{CompileDate:.20s}, {CompileTime:.9s}"
result.add CompileDate.substr(0, 19)
result.add ", "
result.add CompileTime.substr(0, 8)

const buildinfo = getBuildInfo()
proc Py_GetBuildInfo*: string = buildinfo
48 changes: 48 additions & 0 deletions Modules/os_findExe_patch.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

import std/os
import std/strutils

when defined(js) and not compiles(static(fileExists".")):
proc fileExists(fp: string): bool = true # XXX: TODO: I've tried many ways
# to support compile-time check, but Nim just rejects when JS

when true:
# copied from std/os, removed `readlink` part, see `XXX` below
proc findExe*(exe: string, followSymlinks: bool = true;
extensions: openArray[string]=ExeExts): string {.
tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
## Searches for `exe` in the current working directory and then
## in directories listed in the ``PATH`` environment variable.
##
## Returns `""` if the `exe` cannot be found. `exe`
## is added the `ExeExts`_ file extensions if it has none.
##
## If the system supports symlinks it also resolves them until it
## meets the actual file. This behavior can be disabled if desired
## by setting `followSymlinks = false`.

if exe.len == 0: return
template checkCurrentDir() =
for ext in extensions:
result = addFileExt(exe, ext)
if fileExists(result): return
when defined(posix):
if '/' in exe: checkCurrentDir()
else:
checkCurrentDir()
let path = getEnv("PATH")
for candidate in split(path, PathSep):
if candidate.len == 0: continue
when defined(windows):
var x = (if candidate[0] == '"' and candidate[^1] == '"':
substr(candidate, 1, candidate.len-2) else: candidate) /
exe
else:
var x = expandTilde(candidate) / exe
for ext in extensions:
var x = addFileExt(x, ext)
if fileExists(x):
# XXX: there was a branch of `when ...`, which doesn't work on nimvm
# due to `readlink`, so removed
return x
result = ""
67 changes: 67 additions & 0 deletions Objects/abstract.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

import std/strformat
import ./pyobject
import ./numobjects
import ./[iterobject, exceptions, stringobject]
export PyNumber_Index, PyNumber_AsSsize_t, PyNumber_AsClampedSsize_t


template optionalTLikeArg[T](args; i: int, def: T; mapper): T =
if args.len > i: mapper args[i]
else: def

template numAsIntOrRetE*(x: PyObject): int =
## interpret int or int-able object `x` to `system.int`
var res: int
let e = x.PyNumber_AsSsize_t res
if not e.isNil:
return e
res

template numAsClampedIndexOrRetE*(x: PyObject; size: int): int =
## interpret int or int-able object `x` to `system.int`, clamping result in `0..<size`
let intObj = x.PyNumber_Index
if intObj.isThrownException:
return intObj
intObj.PyIntObject.getClampedIndex(size)

template intLikeOptArgAt*(args: seq[PyObject]; i: int, def: int): int =
## parse arg `x: Optional[<object has __index__>] = None`
bind optionalTLikeArg, numAsIntOrRetE
optionalTLikeArg(args, i, def, numAsIntOrRetE)

template clampedIndexOptArgAt*(args: seq[PyObject]; i: int, def: int, size: int): int =
## parse arg `x: Optional[<object has __index__>] = None`, clamped result in `0..<size`
bind optionalTLikeArg, numAsIntOrRetE
template t(x): int{.genSym.} =
numAsClampedIndexOrRetE(x, size)
optionalTLikeArg(args, i, def, t)

template PySequence_Check*(o: PyObject): bool =
## PY-DIFF: we check whether o has items: seq[PyObject]
when not compiles(o.items): false
else: o.items is seq[PyObject]
template ifPySequence_Check*(o: PyObject, body) =
when PySequence_Check(o): body
template ifPySequence_Check*(o: PyObject, body, elseDo): untyped =
when PySequence_Check(o): body
else: elseDo

proc PyIter_Check*(obj: PyObject): bool =
let t = obj.getMagic(iternext)
not t.isNil # PY-DIFF: never be _PyObject_NextNotImplemented

template PyObject_GetIter*(o: PyObject): PyObject =
bind newTypeError, newPyStr, getMagic, newPySeqIter
bind fmt, formatValue
bind ifPySequence_Check
let f = o.getMagic(iter)
if f.isNil:
ifPySequence_Check(o):
newPySeqIter(o.items)
do:
let n{.inject.} = o.pyType.name
newTypeError newPyStr(
fmt"'{n:.200s}' object is not iterable"
)
else: f(o)
10 changes: 7 additions & 3 deletions Objects/boolobject.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import pyobject
declarePyType Bool(tpToken):
b: bool

proc newPyBool(b: bool): PyBoolObject =
proc newPyBoolInner(b: bool): PyBoolObject =
result = newPyBoolSimple()
result.b = b


let pyTrueObj* = newPyBool(true)
let pyFalseObj* = newPyBool(false)
let pyTrueObj* = newPyBoolInner(true) ## singleton
let pyFalseObj* = newPyBoolInner(false) ## singleton

proc newPyBool*(b: bool): PyBoolObject =
if b: pyTrueObj
else: pyFalseObj
63 changes: 38 additions & 25 deletions Objects/boolobjectImpl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@ import macros
import pyobject
import exceptions
import stringobject
import boolobject
import ./boolobject
export boolobject
import numobjects
import ./noneobject

export boolobject

method `$`*(obj: PyBoolObject): string =
$obj.b

methodMacroTmpl(Bool)

implBoolMagic Not:
if self == pyTrueObj:
pyFalseObj
else:
pyTrueObj

newPyBool self != pyTrueObj

implBoolMagic bool:
self
Expand All @@ -29,41 +26,57 @@ implBoolMagic bool:
implBoolMagic And:
let otherBoolObj = other.callMagic(bool)
errorIfNotBool(otherBoolObj, "__bool__")
if self.b and PyBoolObject(otherBoolObj).b:
return pyTrueObj
else:
return pyFalseObj
newPyBool self.b and PyBoolObject(otherBoolObj).b

implBoolMagic Xor:
let otherBoolObj = other.callMagic(bool)
errorIfNotBool(otherBoolObj, "__bool__")
if self.b xor PyBoolObject(otherBoolObj).b:
return pyTrueObj
else:
return pyFalseObj
newPyBool self.b xor PyBoolObject(otherBoolObj).b

implBoolMagic Or:
let otherBoolObj = other.callMagic(bool)
errorIfNotBool(otherBoolObj, "__bool__")
if self.b or PyBoolObject(otherBoolObj).b:
return pyTrueObj
else:
return pyFalseObj
newPyBool self.b or PyBoolObject(otherBoolObj).b

implBoolMagic eq:
let otherBoolObj = other.callMagic(bool)
errorIfNotBool(otherBoolObj, "__bool__")
let otherBool = PyBoolObject(otherBoolObj).b
if self.b == otherBool:
return pyTrueObj
else:
return pyFalseObj
newPyBool self.b == otherBool

implBoolMagic repr:
if self.b:
return newPyString("True")
return newPyAscii("True")
else:
return newPyString("False")
return newPyAscii("False")

implBoolMagic hash:
newPyInt(Hash(self.b))


proc PyObject_IsTrue*(v: PyObject, res: var bool): PyBaseErrorObject =
template ret(b: bool) =
res = b
return nil
if v == pyTrueObj: ret true
if v == pyFalseObj: ret false
if v == pyNone: ret false
let boolMag = v.getMagic(bool)
if not boolMag.isNil:
let obj = boolMag(v)
errorIfNotBool obj, "__bool__"
ret obj.PyBoolObject.b
elif not v.getMagic(len).isNil:
let obj = v.getMagic(len)(v)
errorIfNot int, obj, "__bool__"
ret obj.PyIntObject.positive
# We currently don't define:
# as_sequence
# as_mapping
ret true

implBoolMagic New(tp: PyObject, obj: PyObject):
var b: bool
retIfExc PyObject_IsTrue(obj, b)
newPyBool b

4 changes: 2 additions & 2 deletions Objects/bundle.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import baseBundle
import codeobject, dictobject, frameobject, boolobjectImpl,
listobject, moduleobject, methodobject, funcobject,
pyobject, stringobjectImpl, rangeobject, exceptionsImpl,
sliceobject, tupleobject, cellobject, methodobject
sliceobject, tupleobjectImpl, cellobject, setobject
export baseBundle
export codeobject, dictobject, frameobject, boolobjectImpl,
listobject, moduleobject, methodobject, funcobject,
pyobject, stringobjectImpl, rangeobject, exceptionsImpl,
sliceobject, tupleobject, cellobject, methodobject
sliceobject, tupleobjectImpl, cellobject, setobject
Loading