forked from KolibriOS/kolibrios
Uploaded tinypy sources.
git-svn-id: svn://kolibrios.org@1913 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
00ac1c33b5
commit
9fd32b8cdf
35
programs/develop/tinypy/CHANGES.txt
Normal file
35
programs/develop/tinypy/CHANGES.txt
Normal file
@ -0,0 +1,35 @@
|
||||
== 1.1 =========================================================================
|
||||
* applied patch by Dean Hall to fix several range() bugs
|
||||
* applied patch by Krzysztof Kowalczyk to add VS 2005, 2008 compatibility.
|
||||
* reorganized the source so that contributed modules can go into contrib
|
||||
* reorganized the reorganization so that modules go into modules
|
||||
since that seems less confusing somehow
|
||||
* added a crude pygame module - to see it in action:
|
||||
$ python setup.py linux pygame
|
||||
$ ./build/tinypy examples/julia.py
|
||||
* added support for
|
||||
from x import *
|
||||
from x import y
|
||||
* trimmed off 1064 bytes by changing all the tokens from dicts to
|
||||
a Token class in tokenize, parse, encode modules
|
||||
* applied patch by Seth Lemons to support /* */ comment stripping in
|
||||
setup.py and get tinypy up to -std=c89 spec
|
||||
* cleaned up encode.py so that registers are no longer leaked
|
||||
added assert after each frame to check that this is the case
|
||||
* applied patch by KK to improve tinypy/tests.py feedback
|
||||
* applied patch by allefant to finish namespacing tinypy
|
||||
* applied patch by allefant to keep blob->tinypy.h from having warnings
|
||||
* added math module from Rockins Chen
|
||||
* fixed precedent of **
|
||||
* removed unused tp_data meta methods
|
||||
* made tp_data API "safer" by requiring the magic type
|
||||
* improved setup.py to handle the clean argument
|
||||
* renamed some internal fnc names for no good reason
|
||||
* added boot option to setup.py so that full boostrapping
|
||||
isn't always required
|
||||
* applied const correctness patch from allefant
|
||||
* fixed memory leak in list & dict copy functions
|
||||
* improved kwargs support
|
||||
* got it compiling with -Wc++-compat
|
||||
* applied ord patch from allefant
|
||||
* fixed mingw build
|
82
programs/develop/tinypy/LICENSE.txt
Normal file
82
programs/develop/tinypy/LICENSE.txt
Normal file
@ -0,0 +1,82 @@
|
||||
================================================================================
|
||||
|
||||
tinypy contains tinypy code licensed in a MIT format license. It also
|
||||
contains some goodies grabbed from Python, so that license is included
|
||||
as well.
|
||||
|
||||
================================================================================
|
||||
|
||||
The tinypy License
|
||||
|
||||
Copyright (c) 2008 Phil Hassey
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
================================================================================
|
||||
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python
|
||||
alone or in any derivative version, provided, however, that PSF's
|
||||
License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation;
|
||||
All Rights Reserved" are retained in Python alone or in any derivative
|
||||
version prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
================================================================================
|
62
programs/develop/tinypy/README.txt
Normal file
62
programs/develop/tinypy/README.txt
Normal file
@ -0,0 +1,62 @@
|
||||
64k tinypy
|
||||
"batteries not (yet) included"
|
||||
Copyright (c) 2008 Phil Hassey
|
||||
|
||||
Check it out:
|
||||
|
||||
$ python setup.py linux pygame
|
||||
$ ./build/tinypy examples/julia.py
|
||||
$ ./build/tinypy your-program-goes-here.py
|
||||
|
||||
Depends on:
|
||||
- python (only for bootstrapping)
|
||||
- sdl (for the pygame module)
|
||||
- gcc
|
||||
|
||||
Credits:
|
||||
- math module - Rockins Chen <ybc2084@gmail.com>
|
||||
- VS support - Krzysztof Kowalczyk
|
||||
- bug fixin' - Dean Hall & Allefant
|
||||
|
||||
Thanks to allefant and the python community for all the tips and feedback!
|
||||
Thanks to John M. for a python 2.5 compat. patch.
|
||||
And to illume and the rest of #ludumdare for morale support.
|
||||
Also thanks to python.org, lua.org, valgrind.org, nekovm.org, pypy.org
|
||||
http://javascript.crockford.com/tdop/tdop.html
|
||||
http://www.memorymanagement.org/articles/recycle.html
|
||||
http://shed-skin.blogspot.com/
|
||||
|
||||
Other "tiny" python implementations:
|
||||
http://pymite.python-hosting.com/
|
||||
http://students.ceid.upatras.gr/~sxanth/pyvm/
|
||||
|
||||
F.A.Q.s:
|
||||
|
||||
Q. If I run boot.py it says you've got like 80k of code! That's TOTALLY
|
||||
not 64k! I want my money back.
|
||||
A. Err... that's true. But 64k sounds *SO* much better than 80k.
|
||||
If you *really* want it to be 64k, just run:
|
||||
$ python mk64k.py
|
||||
This does the following things:
|
||||
- changes 4 spaces into tabs and removes blank lines
|
||||
- removes comments
|
||||
- removes the "namespacing" i.e. "tp_print" becomes "print"
|
||||
|
||||
Q. The binary is bigger than 64k. I hate big binaries.
|
||||
A. I don't really care, but if you run "upx tinypy" it makes the tinypy
|
||||
binary smaller than 64k.
|
||||
|
||||
Q. No matter how you spin this, it's just plain NOT 64k.
|
||||
A. Let the buyer beware? I dunno, it's close enough. Let's call it a rounding
|
||||
error, shall we?
|
||||
|
||||
Q. How come some oddball combinations of variable and named arguments don't work?
|
||||
A. Ask me some other time. Short answer: I do it like lua does it. Only calls
|
||||
like this make sense:
|
||||
call_with_var_args(a,b,c,*d)
|
||||
call_with_named_args(a=b,**c)
|
||||
mixes of both just don't work, sorry!
|
||||
|
||||
Q. At the end of build.py tinypy doesn't work!
|
||||
A. This is probably because of my use of -O3 in the final step. Run the command
|
||||
again without -O3. Some versions of GCC are buggy and don't do well with it.
|
55
programs/develop/tinypy/ROADMAP.txt
Normal file
55
programs/develop/tinypy/ROADMAP.txt
Normal file
@ -0,0 +1,55 @@
|
||||
tinypy is a minimalist implementation of python in 64k of code
|
||||
|
||||
"batteries not included (yet)"
|
||||
"lua for people who like python"
|
||||
|
||||
what tinypy is:
|
||||
* parser and bytecode compiler written in tinypy
|
||||
* fully bootstrapped
|
||||
* luaesque virtual machine with garbage collection written in C
|
||||
it's "stackless" sans any "stackless" features
|
||||
* cross-platform :) it runs under windows / linux / macosx
|
||||
* a fairly decent subset of python
|
||||
o classes and single inheritance
|
||||
o functions with variable or keyword arguments
|
||||
o strings, lists, dicts, numbers
|
||||
o modules, list comprehensions
|
||||
o exceptions with full traceback
|
||||
o some builtins
|
||||
- an easy C-API for building modules
|
||||
- 64k of code (for at least some definition of 64k)
|
||||
- interesting, educational, nifty, and useful
|
||||
- well tested
|
||||
- easy to read, maintain, and use
|
||||
- fun fun fun!!!
|
||||
- you can static compile it and its modules (MIT license, so "it's all good!")
|
||||
|
||||
what tinypy will be:
|
||||
- sandboxed
|
||||
- a Cpython module (setup.py install)
|
||||
- including some batteries (math, random, re, marshal, pygame?!)
|
||||
- Visual Studio compatible
|
||||
- documented
|
||||
|
||||
what tinypy might be:
|
||||
- as fast as python (maybe faster?)
|
||||
- including a JIT module
|
||||
- C89 compatible
|
||||
- C++ compatible (like lua)
|
||||
- a shed-skin module
|
||||
- including a dynamic loading module
|
||||
|
||||
what tinypy won't be:
|
||||
- a full implementation of python
|
||||
- totally compatible with python
|
||||
|
||||
alternatives to tinypy:
|
||||
- lua
|
||||
- shed-skin
|
||||
- pymite
|
||||
- pyvm
|
||||
- cython
|
||||
- pypy
|
||||
- jython
|
||||
- ironpython
|
||||
- python
|
42
programs/develop/tinypy/examples/julia.py
Normal file
42
programs/develop/tinypy/examples/julia.py
Normal file
@ -0,0 +1,42 @@
|
||||
# center: 10043
|
||||
import pygame
|
||||
if '.' in str(1.0):
|
||||
import pygame.locals
|
||||
|
||||
SW,SH = 120,120
|
||||
|
||||
def julia(s,ca,cb):
|
||||
pal = [((min(255,v)),(min(255,v*3/2)),(min(255,v*2))) for v in range(0,256)]
|
||||
for y in range(0,SH):
|
||||
for x in range(0,SW):
|
||||
i=0
|
||||
a=((float(x)/SW) * 4.0 - 2.0)
|
||||
b=((float(y)/SH) * 4.0 - 2.0)
|
||||
while i < 15 and (a*a)+(b*b)<4.0:
|
||||
na=(a*a)-(b*b)+ca
|
||||
nb=(2.0*a*b)+cb
|
||||
a=na
|
||||
b=nb
|
||||
i = i +1
|
||||
s.set_at((x,y),pal[i*16])
|
||||
|
||||
def main():
|
||||
pygame.init()
|
||||
s = pygame.display.set_mode((SW,SH),0,32)
|
||||
_quit = False
|
||||
while not _quit:
|
||||
for e in pygame.event.get():
|
||||
if e.type in (pygame.locals.QUIT,pygame.locals.KEYDOWN):
|
||||
_quit = True
|
||||
|
||||
x,y = pygame.mouse.get_pos()
|
||||
ca=((float(x)/SW) * 2.0 - 1.0)
|
||||
cb=((float(y)/SH) * 2.0 - 1.0)
|
||||
ticks = pygame.time.get_ticks()
|
||||
julia(s,ca,cb)
|
||||
print(pygame.time.get_ticks()-ticks)
|
||||
pygame.display.flip()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
66
programs/develop/tinypy/modules/math/init.c
Normal file
66
programs/develop/tinypy/modules/math/init.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "math.c"
|
||||
#include "../../tinypy/tp.h"
|
||||
|
||||
/*
|
||||
* init math module, namely, set its dictionary
|
||||
*/
|
||||
void math_init(TP)
|
||||
{
|
||||
/*
|
||||
* new a module dict for math
|
||||
*/
|
||||
tp_obj math_mod = tp_dict(tp);
|
||||
|
||||
/*
|
||||
* initialize pi and e
|
||||
*/
|
||||
math_pi = tp_number(M_PI);
|
||||
math_e = tp_number(M_E);
|
||||
|
||||
/*
|
||||
* bind math functions to math module
|
||||
*/
|
||||
tp_set(tp, math_mod, tp_string("pi"), math_pi);
|
||||
tp_set(tp, math_mod, tp_string("e"), math_e);
|
||||
tp_set(tp, math_mod, tp_string("acos"), tp_fnc(tp, math_acos));
|
||||
tp_set(tp, math_mod, tp_string("asin"), tp_fnc(tp, math_asin));
|
||||
tp_set(tp, math_mod, tp_string("atan"), tp_fnc(tp, math_atan));
|
||||
tp_set(tp, math_mod, tp_string("atan2"), tp_fnc(tp, math_atan2));
|
||||
tp_set(tp, math_mod, tp_string("ceil"), tp_fnc(tp, math_ceil));
|
||||
tp_set(tp, math_mod, tp_string("cos"), tp_fnc(tp, math_cos));
|
||||
tp_set(tp, math_mod, tp_string("cosh"), tp_fnc(tp, math_cosh));
|
||||
tp_set(tp, math_mod, tp_string("degrees"), tp_fnc(tp, math_degrees));
|
||||
tp_set(tp, math_mod, tp_string("exp"), tp_fnc(tp, math_exp));
|
||||
tp_set(tp, math_mod, tp_string("fabs"), tp_fnc(tp, math_fabs));
|
||||
tp_set(tp, math_mod, tp_string("floor"), tp_fnc(tp, math_floor));
|
||||
tp_set(tp, math_mod, tp_string("fmod"), tp_fnc(tp, math_fmod));
|
||||
tp_set(tp, math_mod, tp_string("frexp"), tp_fnc(tp, math_frexp));
|
||||
tp_set(tp, math_mod, tp_string("hypot"), tp_fnc(tp, math_hypot));
|
||||
tp_set(tp, math_mod, tp_string("ldexp"), tp_fnc(tp, math_ldexp));
|
||||
tp_set(tp, math_mod, tp_string("log"), tp_fnc(tp, math_log));
|
||||
tp_set(tp, math_mod, tp_string("log10"), tp_fnc(tp, math_log10));
|
||||
tp_set(tp, math_mod, tp_string("modf"), tp_fnc(tp, math_modf));
|
||||
tp_set(tp, math_mod, tp_string("pow"), tp_fnc(tp, math_pow));
|
||||
tp_set(tp, math_mod, tp_string("radians"), tp_fnc(tp, math_radians));
|
||||
tp_set(tp, math_mod, tp_string("sin"), tp_fnc(tp, math_sin));
|
||||
tp_set(tp, math_mod, tp_string("sinh"), tp_fnc(tp, math_sinh));
|
||||
tp_set(tp, math_mod, tp_string("sqrt"), tp_fnc(tp, math_sqrt));
|
||||
tp_set(tp, math_mod, tp_string("tan"), tp_fnc(tp, math_tan));
|
||||
tp_set(tp, math_mod, tp_string("tanh"), tp_fnc(tp, math_tanh));
|
||||
|
||||
/*
|
||||
* bind special attributes to math module
|
||||
*/
|
||||
tp_set(tp, math_mod, tp_string("__doc__"),
|
||||
tp_string(
|
||||
"This module is always available. It provides access to the\n"
|
||||
"mathematical functions defined by the C standard."));
|
||||
tp_set(tp, math_mod, tp_string("__name__"), tp_string("math"));
|
||||
tp_set(tp, math_mod, tp_string("__file__"), tp_string(__FILE__));
|
||||
|
||||
/*
|
||||
* bind to tiny modules[]
|
||||
*/
|
||||
tp_set(tp, tp->modules, tp_string("math"), math_mod);
|
||||
}
|
||||
|
365
programs/develop/tinypy/modules/math/math.c
Normal file
365
programs/develop/tinypy/modules/math/math.c
Normal file
@ -0,0 +1,365 @@
|
||||
#include <math.h>
|
||||
#ifndef M_E
|
||||
#define M_E 2.7182818284590452354
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* template for tinypy math functions
|
||||
* with one parameter.
|
||||
*
|
||||
* @cfunc is the coresponding function name in C
|
||||
* math library.
|
||||
*/
|
||||
#define TP_MATH_FUNC1(cfunc) \
|
||||
static tp_obj math_##cfunc(TP) { \
|
||||
double x = TP_NUM(); \
|
||||
double r = 0.0; \
|
||||
\
|
||||
errno = 0; \
|
||||
r = cfunc(x); \
|
||||
if (errno == EDOM || errno == ERANGE) { \
|
||||
tp_raise(tp_None, "%s(x): x=%f, " \
|
||||
"out of range", __func__, x); \
|
||||
} \
|
||||
\
|
||||
return (tp_number(r)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* template for tinypy math functions
|
||||
* with two parameters.
|
||||
*
|
||||
* @cfunc is the coresponding function name in C
|
||||
* math library.
|
||||
*/
|
||||
#define TP_MATH_FUNC2(cfunc) \
|
||||
static tp_obj math_##cfunc(TP) { \
|
||||
double x = TP_NUM(); \
|
||||
double y = TP_NUM(); \
|
||||
double r = 0.0; \
|
||||
\
|
||||
errno = 0; \
|
||||
r = cfunc(x, y); \
|
||||
if (errno == EDOM || errno == ERANGE) { \
|
||||
tp_raise(tp_None, "%s(x, y): x=%f,y=%f " \
|
||||
"out of range", __func__, x, y);\
|
||||
} \
|
||||
\
|
||||
return (tp_number(r)); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PI definition: 3.1415926535897931
|
||||
*/
|
||||
static tp_obj math_pi;
|
||||
|
||||
/*
|
||||
* E definition: 2.7182818284590451
|
||||
*/
|
||||
static tp_obj math_e;
|
||||
|
||||
/*
|
||||
* acos(x)
|
||||
*
|
||||
* return arc cosine of x, return value is measured in radians.
|
||||
* if x falls out -1 to 1, raise out-of-range exception.
|
||||
*/
|
||||
TP_MATH_FUNC1(acos)
|
||||
|
||||
/*
|
||||
* asin(x)
|
||||
*
|
||||
* return arc sine of x, measured in radians, actually [-PI/2, PI/2]
|
||||
* if x falls out of -1 to 1, raise out-of-range exception
|
||||
*/
|
||||
TP_MATH_FUNC1(asin)
|
||||
|
||||
/*
|
||||
* atan(x)
|
||||
*
|
||||
* return arc tangent of x, measured in radians,
|
||||
*/
|
||||
TP_MATH_FUNC1(atan)
|
||||
|
||||
/*
|
||||
* atan2(x, y)
|
||||
*
|
||||
* return arc tangent of x/y, measured in radians.
|
||||
* unlike atan(x/y), both the signs of x and y
|
||||
* are considered to determine the quaderant of
|
||||
* the result.
|
||||
*/
|
||||
TP_MATH_FUNC2(atan2)
|
||||
|
||||
/*
|
||||
* ceil(x)
|
||||
*
|
||||
* return the ceiling of x, i.e, the smallest
|
||||
* integer >= x.
|
||||
*/
|
||||
TP_MATH_FUNC1(ceil)
|
||||
|
||||
/*
|
||||
* cos(x)
|
||||
*
|
||||
* return cosine of x. x is measured in radians.
|
||||
*/
|
||||
TP_MATH_FUNC1(cos)
|
||||
|
||||
/*
|
||||
* cosh(x)
|
||||
*
|
||||
* return hyperbolic cosine of x.
|
||||
*/
|
||||
TP_MATH_FUNC1(cosh)
|
||||
|
||||
/*
|
||||
* degrees(x)
|
||||
*
|
||||
* converts angle x from radians to degrees.
|
||||
* NOTE: this function is introduced by python,
|
||||
* so we cannot wrap it directly in TP_MATH_FUNC1(),
|
||||
* here the solution is defining a new
|
||||
* C function - degrees().
|
||||
*/
|
||||
static const double degToRad =
|
||||
3.141592653589793238462643383 / 180.0;
|
||||
static double degrees(double x)
|
||||
{
|
||||
return (x / degToRad);
|
||||
}
|
||||
|
||||
TP_MATH_FUNC1(degrees)
|
||||
|
||||
/*
|
||||
* exp(x)
|
||||
*
|
||||
* return the value e raised to power of x.
|
||||
* e is the base of natural logarithms.
|
||||
*/
|
||||
TP_MATH_FUNC1(exp)
|
||||
|
||||
/*
|
||||
* fabs(x)
|
||||
*
|
||||
* return the absolute value of x.
|
||||
*/
|
||||
TP_MATH_FUNC1(fabs)
|
||||
|
||||
/*
|
||||
* floor(x)
|
||||
*
|
||||
* return the floor of x, i.e, the largest integer <= x
|
||||
*/
|
||||
TP_MATH_FUNC1(floor)
|
||||
|
||||
/*
|
||||
* fmod(x, y)
|
||||
*
|
||||
* return the remainder of dividing x by y. that is,
|
||||
* return x - n * y, where n is the quotient of x/y.
|
||||
* NOTE: this function relies on the underlying platform.
|
||||
*/
|
||||
TP_MATH_FUNC2(fmod)
|
||||
|
||||
/*
|
||||
* frexp(x)
|
||||
*
|
||||
* return a pair (r, y), which satisfies:
|
||||
* x = r * (2 ** y), and r is normalized fraction
|
||||
* which is laid between 1/2 <= abs(r) < 1.
|
||||
* if x = 0, the (r, y) = (0, 0).
|
||||
*/
|
||||
static tp_obj math_frexp(TP) {
|
||||
double x = TP_NUM();
|
||||
int y = 0;
|
||||
double r = 0.0;
|
||||
tp_obj rList = tp_list(tp);
|
||||
|
||||
errno = 0;
|
||||
r = frexp(x, &y);
|
||||
if (errno == EDOM || errno == ERANGE) {
|
||||
tp_raise(tp_None, "%s(x): x=%f, "
|
||||
"out of range", __func__, x);
|
||||
}
|
||||
|
||||
_tp_list_append(tp, rList.list.val, tp_number(r));
|
||||
_tp_list_append(tp, rList.list.val, tp_number((tp_num)y));
|
||||
return (rList);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hypot(x, y)
|
||||
*
|
||||
* return Euclidean distance, namely,
|
||||
* sqrt(x*x + y*y)
|
||||
*/
|
||||
TP_MATH_FUNC2(hypot)
|
||||
|
||||
|
||||
/*
|
||||
* ldexp(x, y)
|
||||
*
|
||||
* return the result of multiplying x by 2
|
||||
* raised to y.
|
||||
*/
|
||||
TP_MATH_FUNC2(ldexp)
|
||||
|
||||
/*
|
||||
* log(x, [base])
|
||||
*
|
||||
* return logarithm of x to given base. If base is
|
||||
* not given, return the natural logarithm of x.
|
||||
* Note: common logarithm(log10) is used to compute
|
||||
* the denominator and numerator. based on fomula:
|
||||
* log(x, base) = log10(x) / log10(base).
|
||||
*/
|
||||
static tp_obj math_log(TP) {
|
||||
double x = TP_NUM();
|
||||
tp_obj b = TP_DEFAULT(tp_None);
|
||||
double y = 0.0;
|
||||
double den = 0.0; /* denominator */
|
||||
double num = 0.0; /* numinator */
|
||||
double r = 0.0; /* result */
|
||||
|
||||
if (b.type == TP_NONE)
|
||||
y = M_E;
|
||||
else if (b.type == TP_NUMBER)
|
||||
y = (double)b.number.val;
|
||||
else
|
||||
tp_raise(tp_None, "%s(x, [base]): base invalid", __func__);
|
||||
|
||||
errno = 0;
|
||||
num = log10(x);
|
||||
if (errno == EDOM || errno == ERANGE)
|
||||
goto excep;
|
||||
|
||||
errno = 0;
|
||||
den = log10(y);
|
||||
if (errno == EDOM || errno == ERANGE)
|
||||
goto excep;
|
||||
|
||||
r = num / den;
|
||||
|
||||
return (tp_number(r));
|
||||
|
||||
excep:
|
||||
tp_raise(tp_None, "%s(x, y): x=%f,y=%f "
|
||||
"out of range", __func__, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* log10(x)
|
||||
*
|
||||
* return 10-based logarithm of x.
|
||||
*/
|
||||
TP_MATH_FUNC1(log10)
|
||||
|
||||
/*
|
||||
* modf(x)
|
||||
*
|
||||
* return a pair (r, y). r is the integral part of
|
||||
* x and y is the fractional part of x, both holds
|
||||
* the same sign as x.
|
||||
*/
|
||||
static tp_obj math_modf(TP) {
|
||||
double x = TP_NUM();
|
||||
double y = 0.0;
|
||||
double r = 0.0;
|
||||
tp_obj rList = tp_list(tp);
|
||||
|
||||
errno = 0;
|
||||
r = modf(x, &y);
|
||||
if (errno == EDOM || errno == ERANGE) {
|
||||
tp_raise(tp_None, "%s(x): x=%f, "
|
||||
"out of range", __func__, x);
|
||||
}
|
||||
|
||||
_tp_list_append(tp, rList.list.val, tp_number(r));
|
||||
_tp_list_append(tp, rList.list.val, tp_number(y));
|
||||
return (rList);
|
||||
}
|
||||
|
||||
/*
|
||||
* pow(x, y)
|
||||
*
|
||||
* return value of x raised to y. equivalence of x ** y.
|
||||
* NOTE: conventionally, tp_pow() is the implementation
|
||||
* of builtin function pow(); whilst, math_pow() is an
|
||||
* alternative in math module.
|
||||
*/
|
||||
static tp_obj math_pow(TP) {
|
||||
double x = TP_NUM();
|
||||
double y = TP_NUM();
|
||||
double r = 0.0;
|
||||
|
||||
errno = 0;
|
||||
r = pow(x, y);
|
||||
if (errno == EDOM || errno == ERANGE) {
|
||||
tp_raise(tp_None, "%s(x, y): x=%f,y=%f "
|
||||
"out of range", __func__, x, y);
|
||||
}
|
||||
|
||||
return (tp_number(r));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* radians(x)
|
||||
*
|
||||
* converts angle x from degrees to radians.
|
||||
* NOTE: this function is introduced by python,
|
||||
* adopt same solution as degrees(x).
|
||||
*/
|
||||
static double radians(double x)
|
||||
{
|
||||
return (x * degToRad);
|
||||
}
|
||||
|
||||
TP_MATH_FUNC1(radians)
|
||||
|
||||
/*
|
||||
* sin(x)
|
||||
*
|
||||
* return sine of x, x is measured in radians.
|
||||
*/
|
||||
TP_MATH_FUNC1(sin)
|
||||
|
||||
/*
|
||||
* sinh(x)
|
||||
*
|
||||
* return hyperbolic sine of x.
|
||||
* mathematically, sinh(x) = (exp(x) - exp(-x)) / 2.
|
||||
*/
|
||||
TP_MATH_FUNC1(sinh)
|
||||
|
||||
/*
|
||||
* sqrt(x)
|
||||
*
|
||||
* return square root of x.
|
||||
* if x is negtive, raise out-of-range exception.
|
||||
*/
|
||||
TP_MATH_FUNC1(sqrt)
|
||||
|
||||
/*
|
||||
* tan(x)
|
||||
*
|
||||
* return tangent of x, x is measured in radians.
|
||||
*/
|
||||
TP_MATH_FUNC1(tan)
|
||||
|
||||
/*
|
||||
* tanh(x)
|
||||
*
|
||||
* return hyperbolic tangent of x.
|
||||
* mathematically, tanh(x) = sinh(x) / cosh(x).
|
||||
*/
|
||||
TP_MATH_FUNC1(tanh)
|
||||
|
176
programs/develop/tinypy/modules/math/tests.py
Normal file
176
programs/develop/tinypy/modules/math/tests.py
Normal file
@ -0,0 +1,176 @@
|
||||
### This file is grabbed from Python's Lib/test/test_math.py
|
||||
###---------------------------------------------------------
|
||||
# Python test set -- math module
|
||||
# XXXX Should not do tests around zero only
|
||||
|
||||
eps = 0.00001
|
||||
#print('math module, testing with eps ', eps)
|
||||
import math
|
||||
|
||||
def testit(name, value, expected):
|
||||
if abs(value-expected) > eps:
|
||||
msg = name + " returned " + str(value) + " expected " + str(expected)
|
||||
raise msg
|
||||
|
||||
#print 'constants'
|
||||
testit('pi', math.pi, 3.1415926)
|
||||
testit('e', math.e, 2.7182818)
|
||||
|
||||
#print 'acos'
|
||||
testit('acos(-1)', math.acos(-1), math.pi)
|
||||
testit('acos(0)', math.acos(0), math.pi/2)
|
||||
testit('acos(1)', math.acos(1), 0)
|
||||
|
||||
#print 'asin'
|
||||
testit('asin(-1)', math.asin(-1), -math.pi/2)
|
||||
testit('asin(0)', math.asin(0), 0)
|
||||
testit('asin(1)', math.asin(1), math.pi/2)
|
||||
|
||||
#print 'atan'
|
||||
testit('atan(-1)', math.atan(-1), -math.pi/4)
|
||||
testit('atan(0)', math.atan(0), 0)
|
||||
testit('atan(1)', math.atan(1), math.pi/4)
|
||||
|
||||
#print 'atan2'
|
||||
testit('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
|
||||
testit('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
|
||||
testit('atan2(0, 1)', math.atan2(0, 1), 0)
|
||||
testit('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
|
||||
testit('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
|
||||
|
||||
#print 'ceil'
|
||||
testit('ceil(0.5)', math.ceil(0.5), 1)
|
||||
testit('ceil(1.0)', math.ceil(1.0), 1)
|
||||
testit('ceil(1.5)', math.ceil(1.5), 2)
|
||||
testit('ceil(-0.5)', math.ceil(-0.5), 0)
|
||||
testit('ceil(-1.0)', math.ceil(-1.0), -1)
|
||||
testit('ceil(-1.5)', math.ceil(-1.5), -1)
|
||||
|
||||
#print 'cos'
|
||||
testit('cos(-pi/2)', math.cos(-math.pi/2), 0)
|
||||
testit('cos(0)', math.cos(0), 1)
|
||||
testit('cos(pi/2)', math.cos(math.pi/2), 0)
|
||||
testit('cos(pi)', math.cos(math.pi), -1)
|
||||
|
||||
#print 'cosh'
|
||||
testit('cosh(0)', math.cosh(0), 1)
|
||||
testit('cosh(2)-2*(cosh(1)**2)', math.cosh(2)-2*(math.cosh(1)**2), -1) # Thanks to Lambert
|
||||
|
||||
#print 'degrees'
|
||||
testit('degrees(pi)', math.degrees(math.pi), 180.0)
|
||||
testit('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
|
||||
testit('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
|
||||
|
||||
#print 'exp'
|
||||
testit('exp(-1)', math.exp(-1), 1/math.e)
|
||||
testit('exp(0)', math.exp(0), 1)
|
||||
testit('exp(1)', math.exp(1), math.e)
|
||||
|
||||
#print 'fabs'
|
||||
testit('fabs(-1)', math.fabs(-1), 1)
|
||||
testit('fabs(0)', math.fabs(0), 0)
|
||||
testit('fabs(1)', math.fabs(1), 1)
|
||||
|
||||
#print 'floor'
|
||||
testit('floor(0.5)', math.floor(0.5), 0)
|
||||
testit('floor(1.0)', math.floor(1.0), 1)
|
||||
testit('floor(1.5)', math.floor(1.5), 1)
|
||||
testit('floor(-0.5)', math.floor(-0.5), -1)
|
||||
testit('floor(-1.0)', math.floor(-1.0), -1)
|
||||
testit('floor(-1.5)', math.floor(-1.5), -2)
|
||||
|
||||
#print 'fmod'
|
||||
testit('fmod(10,1)', math.fmod(10,1), 0)
|
||||
testit('fmod(10,0.5)', math.fmod(10,0.5), 0)
|
||||
testit('fmod(10,1.5)', math.fmod(10,1.5), 1)
|
||||
testit('fmod(-10,1)', math.fmod(-10,1), 0)
|
||||
testit('fmod(-10,0.5)', math.fmod(-10,0.5), 0)
|
||||
testit('fmod(-10,1.5)', math.fmod(-10,1.5), -1)
|
||||
|
||||
#print 'frexp'
|
||||
def testfrexp(name, value, expected):
|
||||
mant = value[0]
|
||||
exp = value[1]
|
||||
emant = expected[0]
|
||||
eexp = expected[1]
|
||||
if abs(mant-emant) > eps or exp != eexp:
|
||||
raise '%s returned (%f, %f), expected (%f, %f)'%\
|
||||
(name, mant, exp, emant,eexp)
|
||||
|
||||
testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
|
||||
testfrexp('frexp(0)', math.frexp(0), (0, 0))
|
||||
testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
|
||||
testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
|
||||
|
||||
#print 'hypot'
|
||||
testit('hypot(0,0)', math.hypot(0,0), 0)
|
||||
testit('hypot(3,4)', math.hypot(3,4), 5)
|
||||
|
||||
#print 'ldexp'
|
||||
testit('ldexp(0,1)', math.ldexp(0,1), 0)
|
||||
testit('ldexp(1,1)', math.ldexp(1,1), 2)
|
||||
testit('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
|
||||
testit('ldexp(-1,1)', math.ldexp(-1,1), -2)
|
||||
|
||||
#print 'log'
|
||||
testit('log(1/e)', math.log(1/math.e), -1)
|
||||
testit('log(1)', math.log(1), 0)
|
||||
testit('log(e)', math.log(math.e), 1)
|
||||
testit('log(32,2)', math.log(32,2), 5)
|
||||
testit('log(10**40, 10)', math.log(10**40, 10), 40)
|
||||
testit('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
|
||||
|
||||
#print 'log10'
|
||||
testit('log10(0.1)', math.log10(0.1), -1)
|
||||
testit('log10(1)', math.log10(1), 0)
|
||||
testit('log10(10)', math.log10(10), 1)
|
||||
|
||||
#print 'modf'
|
||||
def testmodf(name, value, expected):
|
||||
v1 = value[0]
|
||||
v2 = value[1]
|
||||
e1 = expected[0]
|
||||
e2 = expected[1]
|
||||
if abs(v1-e1) > eps or abs(v2-e2):
|
||||
raise '%s returned (%f, %f), expected (%f, %f)'%\
|
||||
(name, v1,v2, e1,e2)
|
||||
|
||||
testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
|
||||
testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
|
||||
|
||||
#print 'pow'
|
||||
testit('pow(0,1)', math.pow(0,1), 0)
|
||||
testit('pow(1,0)', math.pow(1,0), 1)
|
||||
testit('pow(2,1)', math.pow(2,1), 2)
|
||||
testit('pow(2,-1)', math.pow(2,-1), 0.5)
|
||||
|
||||
#print 'radians'
|
||||
testit('radians(180)', math.radians(180), math.pi)
|
||||
testit('radians(90)', math.radians(90), math.pi/2)
|
||||
testit('radians(-45)', math.radians(-45), -math.pi/4)
|
||||
|
||||
#print 'sin'
|
||||
testit('sin(0)', math.sin(0), 0)
|
||||
testit('sin(pi/2)', math.sin(math.pi/2), 1)
|
||||
testit('sin(-pi/2)', math.sin(-math.pi/2), -1)
|
||||
|
||||
#print 'sinh'
|
||||
testit('sinh(0)', math.sinh(0), 0)
|
||||
testit('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
|
||||
testit('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
|
||||
|
||||
#print 'sqrt'
|
||||
testit('sqrt(0)', math.sqrt(0), 0)
|
||||
testit('sqrt(1)', math.sqrt(1), 1)
|
||||
testit('sqrt(4)', math.sqrt(4), 2)
|
||||
|
||||
#print 'tan'
|
||||
testit('tan(0)', math.tan(0), 0)
|
||||
testit('tan(pi/4)', math.tan(math.pi/4), 1)
|
||||
testit('tan(-pi/4)', math.tan(-math.pi/4), -1)
|
||||
|
||||
#print 'tanh'
|
||||
testit('tanh(0)', math.tanh(0), 0)
|
||||
testit('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
|
||||
|
||||
#print("OK: math module test pass")
|
182
programs/develop/tinypy/modules/pygame/init.c
Normal file
182
programs/develop/tinypy/modules/pygame/init.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include "SDL.h"
|
||||
|
||||
/* utility functions */
|
||||
Uint32 pygame_list_to_color(TP,tp_obj clr,SDL_Surface *s) {
|
||||
int r,g,b;
|
||||
r = tp_get(tp,clr,tp_number(0)).number.val;
|
||||
g = tp_get(tp,clr,tp_number(1)).number.val;
|
||||
b = tp_get(tp,clr,tp_number(2)).number.val;
|
||||
return SDL_MapRGB(s->format,r,g,b);
|
||||
}
|
||||
|
||||
/* surface */
|
||||
|
||||
#define PYGAME_TYPE_SURF 0x1001
|
||||
|
||||
void pygame_surf_free(TP,tp_obj d) {
|
||||
if (d.data.magic != PYGAME_TYPE_SURF) { tp_raise(,"%s","not a surface"); }
|
||||
SDL_FreeSurface((SDL_Surface*)d.data.val);
|
||||
}
|
||||
|
||||
SDL_Surface *pygame_obj_to_surf(TP,tp_obj self) {
|
||||
tp_obj d = tp_get(tp,self,tp_string("__surf"));
|
||||
if (d.data.magic != PYGAME_TYPE_SURF) { tp_raise(0,"%s","not a surface"); }
|
||||
return (SDL_Surface*)d.data.val;
|
||||
}
|
||||
|
||||
|
||||
tp_obj pygame_surface_set_at(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
tp_obj pos = TP_TYPE(TP_LIST);
|
||||
tp_obj clr = TP_TYPE(TP_LIST);
|
||||
SDL_Rect r;
|
||||
r.x = tp_get(tp,pos,tp_number(0)).number.val;
|
||||
r.y = tp_get(tp,pos,tp_number(1)).number.val;
|
||||
r.w = 1; r.h = 1;
|
||||
SDL_Surface *s =pygame_obj_to_surf(tp,self);
|
||||
Uint32 c = pygame_list_to_color(tp,clr,s);
|
||||
SDL_FillRect(s, &r, c);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
|
||||
tp_obj pygame_surf_to_obj(TP,SDL_Surface *s) {
|
||||
tp_obj self = tp_dict(tp);
|
||||
|
||||
tp_obj d = tp_data(tp,PYGAME_TYPE_SURF,s);
|
||||
d.data.info->free = pygame_surf_free;
|
||||
|
||||
tp_set(tp,self,tp_string("__surf"),d);
|
||||
tp_set(tp,self,tp_string("set_at"),tp_method(tp,self,pygame_surface_set_at));
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* display module */
|
||||
|
||||
tp_obj pygame_display_set_mode(TP) {
|
||||
tp_obj sz = TP_TYPE(TP_LIST);
|
||||
int w = tp_get(tp,sz,tp_number(0)).number.val;
|
||||
int h = tp_get(tp,sz,tp_number(1)).number.val;
|
||||
SDL_Surface *s = SDL_SetVideoMode(w, h, 0, 0);
|
||||
return pygame_surf_to_obj(tp,s);
|
||||
}
|
||||
|
||||
tp_obj pygame_display_flip(TP) {
|
||||
SDL_Flip(SDL_GetVideoSurface());
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
SDL_Rect pygame_list_to_rect(TP,tp_obj o) {
|
||||
SDL_Rect r;
|
||||
r.x = tp_get(tp,o,tp_number(0)).number.val;
|
||||
r.y = tp_get(tp,o,tp_number(1)).number.val;
|
||||
r.w = tp_get(tp,o,tp_number(2)).number.val;
|
||||
r.h = tp_get(tp,o,tp_number(3)).number.val;
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj pygame_display_update(TP) {
|
||||
SDL_Rect r = pygame_list_to_rect(tp,TP_TYPE(TP_LIST));
|
||||
SDL_UpdateRects(SDL_GetVideoSurface(), 1, &r);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
/* event module */
|
||||
tp_obj pygame_event_get(TP) {
|
||||
SDL_Event e;
|
||||
tp_obj r = tp_list(tp);
|
||||
while (SDL_PollEvent(&e)) {
|
||||
tp_obj d = tp_dict(tp);
|
||||
tp_set(tp,d,tp_string("type"),tp_number(e.type));
|
||||
switch (e.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
tp_set(tp,d,tp_string("key"),tp_number(e.key.keysym.sym));
|
||||
tp_set(tp,d,tp_string("mod"),tp_number(e.key.keysym.mod));
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
tp_set(tp,d,tp_string("pos"),tp_list_n(tp,2,(tp_obj[]){tp_number(e.motion.x),tp_number(e.motion.y)}));
|
||||
tp_set(tp,d,tp_string("rel"),tp_list_n(tp,2,(tp_obj[]){tp_number(e.motion.xrel),tp_number(e.motion.yrel)}));
|
||||
tp_set(tp,d,tp_string("state"),tp_number(e.motion.state));
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
tp_set(tp,d,tp_string("pos"),tp_list_n(tp,2,(tp_obj[]){tp_number(e.button.x),tp_number(e.button.y)}));
|
||||
tp_set(tp,d,tp_string("button"),tp_number(e.button.button));
|
||||
break;
|
||||
}
|
||||
tp_set(tp,r,tp_None,d);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* mouse */
|
||||
tp_obj pygame_mouse_get_pos(TP) {
|
||||
int x,y;
|
||||
SDL_GetMouseState(&x,&y);
|
||||
tp_obj r = tp_list_n(tp,2,(tp_obj[]){tp_number(x),tp_number(y)});
|
||||
return r;
|
||||
}
|
||||
|
||||
/* time */
|
||||
tp_obj pygame_time_get_ticks(TP) {
|
||||
return tp_number(SDL_GetTicks());
|
||||
}
|
||||
|
||||
|
||||
/* pygame */
|
||||
#define PYGAME_LOCALS(a,b) tp_set(tp,m,tp_string(a),tp_number(b));
|
||||
|
||||
tp_obj _pygame_init(TP) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
|
||||
void pygame_init(TP) {
|
||||
tp_obj g,m;
|
||||
g = tp_dict(tp);
|
||||
tp_set(tp,tp->modules,tp_string("pygame"),g);
|
||||
tp_set(tp,g,tp_string("init"),tp_fnc(tp,_pygame_init));
|
||||
|
||||
/* display */
|
||||
m = tp_dict(tp); tp_set(tp,g,tp_string("display"),m);
|
||||
tp_set(tp,m,tp_string("set_mode"),tp_fnc(tp,pygame_display_set_mode));
|
||||
tp_set(tp,m,tp_string("flip"),tp_fnc(tp,pygame_display_flip));
|
||||
tp_set(tp,m,tp_string("update"),tp_fnc(tp,pygame_display_update));
|
||||
|
||||
/* event */
|
||||
m = tp_dict(tp); tp_set(tp,g,tp_string("event"),m);
|
||||
tp_set(tp,m,tp_string("get"),tp_fnc(tp,pygame_event_get));
|
||||
|
||||
/* locals */
|
||||
m = tp_dict(tp); tp_set(tp,g,tp_string("locals"),m);
|
||||
PYGAME_LOCALS("QUIT",SDL_QUIT);
|
||||
PYGAME_LOCALS("KEYDOWN",SDL_KEYDOWN);
|
||||
PYGAME_LOCALS("KEYUP",SDL_KEYUP);
|
||||
PYGAME_LOCALS("MOUSEBUTTONDOWN",SDL_MOUSEBUTTONDOWN);
|
||||
PYGAME_LOCALS("MOUSEBUTTONUP",SDL_MOUSEBUTTONUP);
|
||||
PYGAME_LOCALS("MOUSEMOTION",SDL_MOUSEMOTION);
|
||||
PYGAME_LOCALS("K_UP",SDLK_UP);
|
||||
PYGAME_LOCALS("K_DOWN",SDLK_DOWN);
|
||||
PYGAME_LOCALS("K_LEFT",SDLK_LEFT);
|
||||
PYGAME_LOCALS("K_RIGHT",SDLK_RIGHT);
|
||||
PYGAME_LOCALS("K_ESCAPE",SDLK_ESCAPE);
|
||||
PYGAME_LOCALS("K_SPACE",SDLK_SPACE);
|
||||
PYGAME_LOCALS("K_RETURN",SDLK_RETURN);
|
||||
|
||||
/* mouse */
|
||||
m = tp_dict(tp); tp_set(tp,g,tp_string("mouse"),m);
|
||||
tp_set(tp,m,tp_string("get_pos"),tp_fnc(tp,pygame_mouse_get_pos));
|
||||
|
||||
/* time */
|
||||
m = tp_dict(tp); tp_set(tp,g,tp_string("time"),m);
|
||||
tp_set(tp,m,tp_string("get_ticks"),tp_fnc(tp,pygame_time_get_ticks));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**/
|
383
programs/develop/tinypy/setup.py
Normal file
383
programs/develop/tinypy/setup.py
Normal file
@ -0,0 +1,383 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
VARS = {}
|
||||
TOPDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
TEST = False
|
||||
CLEAN = False
|
||||
BOOT = False
|
||||
CORE = ['tokenize','parse','encode','py2bc']
|
||||
MODULES = []
|
||||
|
||||
def main():
|
||||
chksize()
|
||||
if len(sys.argv) < 2:
|
||||
print HELP
|
||||
return
|
||||
|
||||
global TEST,CLEAN,BOOT
|
||||
TEST = 'test' in sys.argv
|
||||
CLEAN = 'clean' in sys.argv
|
||||
BOOT = 'boot' in sys.argv
|
||||
CLEAN = CLEAN or BOOT
|
||||
TEST = TEST or BOOT
|
||||
|
||||
get_libs()
|
||||
build_mymain()
|
||||
|
||||
cmd = sys.argv[1]
|
||||
if cmd == 'linux':
|
||||
vars_linux()
|
||||
build_gcc()
|
||||
elif cmd == 'mingw':
|
||||
vars_windows()
|
||||
build_gcc()
|
||||
elif cmd == 'vs':
|
||||
build_vs()
|
||||
elif cmd == '64k':
|
||||
build_64k()
|
||||
elif cmd == 'blob':
|
||||
build_blob()
|
||||
else:
|
||||
print 'invalid command'
|
||||
|
||||
HELP = """
|
||||
python setup.py command [options] [modules]
|
||||
|
||||
Commands:
|
||||
linux - build tinypy for linux
|
||||
mingw - build tinypy for mingw under windows
|
||||
vs - build tinypy using Visual Studio 2005 / 2008
|
||||
|
||||
64k - build a 64k version of the tinypy source
|
||||
blob - build a single tinypy.c and tinypy.h
|
||||
|
||||
build - build CPython module ***
|
||||
install - install CPython module ***
|
||||
|
||||
Options:
|
||||
test - run tests during build
|
||||
clean - rebuild all .tpc during build
|
||||
boot - fully bootstrap and test tinypy
|
||||
|
||||
Modules:
|
||||
math - build math module
|
||||
random - build random module *
|
||||
pygame - build pygame module **
|
||||
marshal - build marshal module ***
|
||||
jit - build jit module ***
|
||||
re - build re module ***
|
||||
|
||||
* coming soon!!
|
||||
** proof-of-concept included
|
||||
*** vaporware
|
||||
"""
|
||||
|
||||
def vars_linux():
|
||||
VARS['$RM'] = 'rm -f'
|
||||
VARS['$VM'] = './vm'
|
||||
VARS['$TINYPY'] = './tinypy'
|
||||
VARS['$SYS'] = '-linux'
|
||||
VARS['$FLAGS'] = ''
|
||||
|
||||
VARS['$WFLAGS'] = '-std=c89 -Wall -Wc++-compat'
|
||||
#-Wwrite-strings - i think this is included in -Wc++-compat
|
||||
|
||||
if 'pygame' in MODULES:
|
||||
VARS['$FLAGS'] += ' `sdl-config --cflags --libs` '
|
||||
|
||||
def vars_windows():
|
||||
VARS['$RM'] = 'del'
|
||||
VARS['$VM'] = 'vm'
|
||||
VARS['$TINYPY'] = 'tinypy'
|
||||
VARS['$FLAGS'] = '-lmingw32'
|
||||
VARS['$WFLAGS'] = '-Wwrite-strings -Wall'
|
||||
VARS['$SYS'] = '-mingw32'
|
||||
|
||||
if 'pygame' in MODULES:
|
||||
VARS['$FLAGS'] += ' -Ic:\\mingw\\include\\SDL -lSDLmain -lSDL '
|
||||
|
||||
def do_cmd(cmd):
|
||||
for k,v in VARS.items():
|
||||
cmd = cmd.replace(k,v)
|
||||
if '$' in cmd:
|
||||
print 'vars_error',cmd
|
||||
sys.exit(-1)
|
||||
|
||||
print cmd
|
||||
r = os.system(cmd)
|
||||
if r:
|
||||
print 'exit_status',r
|
||||
sys.exit(r)
|
||||
|
||||
def do_chdir(dest):
|
||||
print 'cd',dest
|
||||
os.chdir(dest)
|
||||
|
||||
def build_bc(opt=False):
|
||||
out = []
|
||||
for mod in CORE:
|
||||
out.append("""unsigned char tp_%s[] = {"""%mod)
|
||||
fname = mod+".tpc"
|
||||
data = open(fname,'rb').read()
|
||||
cols = 16
|
||||
for n in xrange(0,len(data),cols):
|
||||
out.append(",".join([str(ord(v)) for v in data[n:n+cols]])+',')
|
||||
out.append("""};""")
|
||||
out.append("")
|
||||
f = open('bc.c','wb')
|
||||
f.write('\n'.join(out))
|
||||
f.close()
|
||||
|
||||
def open_tinypy(fname,*args):
|
||||
return open(os.path.join(TOPDIR,'tinypy',fname),*args)
|
||||
|
||||
def build_blob():
|
||||
mods = CORE[:]
|
||||
do_chdir(os.path.join(TOPDIR,'tinypy'))
|
||||
for mod in mods: do_cmd('python py2bc.py %s.py %s.tpc'%(mod,mod))
|
||||
do_chdir(os.path.join(TOPDIR))
|
||||
|
||||
out = []
|
||||
out.append("/*")
|
||||
out.extend([v.rstrip() for v in open(os.path.join(TOPDIR,'LICENSE.txt'),'r')])
|
||||
out.append("*/")
|
||||
out.append("")
|
||||
|
||||
out.append("#ifndef TINYPY_H")
|
||||
out.append("#define TINYPY_H")
|
||||
out.extend([v.rstrip() for v in open_tinypy('tp.h','r')])
|
||||
for fname in ['list.c','dict.c','misc.c','string.c','builtins.c',
|
||||
'gc.c','ops.c','vm.c','tp.c']:
|
||||
for line in open_tinypy(fname,'r'):
|
||||
line = line.rstrip()
|
||||
if not len(line): continue
|
||||
if line[0] == '/': continue
|
||||
if line[0] == ' ': continue
|
||||
if line[0] == '\t': continue
|
||||
if line[-1] != '{': continue
|
||||
if 'enum' in line: continue
|
||||
if '=' in line: continue
|
||||
if '#' in line: continue
|
||||
line = line.replace('{',';')
|
||||
|
||||
# Do not include prototypes already defined earlier, or gcc will
|
||||
# warn about doubled prototypes in user code.
|
||||
if '(' in line:
|
||||
line2 = line[:line.find('(') + 1]
|
||||
got_already = False
|
||||
for already in out:
|
||||
if already.startswith(line2):
|
||||
got_already = True
|
||||
break
|
||||
if got_already: continue
|
||||
out.append(line)
|
||||
out.append("#endif")
|
||||
out.append('')
|
||||
dest = os.path.join(TOPDIR,'build','tinypy.h')
|
||||
print 'writing %s'%dest
|
||||
f = open(dest,'w')
|
||||
f.write('\n'.join(out))
|
||||
f.close()
|
||||
|
||||
# we leave all the tinypy.h stuff at the top so that
|
||||
# if someone wants to include tinypy.c they don't have to have
|
||||
# tinypy.h cluttering up their folder
|
||||
|
||||
for mod in CORE:
|
||||
out.append("""extern unsigned char tp_%s[];"""%mod)
|
||||
|
||||
for fname in ['list.c','dict.c','misc.c','string.c','builtins.c',
|
||||
'gc.c','ops.c','vm.c','tp.c','bc.c']:
|
||||
for line in open_tinypy(fname,'r'):
|
||||
line = line.rstrip()
|
||||
if line.find('#include "') != -1: continue
|
||||
out.append(line)
|
||||
out.append('')
|
||||
dest = os.path.join(TOPDIR,'build','tinypy.c')
|
||||
print 'writing %s'%dest
|
||||
f = open(dest,'w')
|
||||
f.write('\n'.join(out))
|
||||
f.close()
|
||||
|
||||
def py2bc(cmd,mod):
|
||||
src = '%s.py'%mod
|
||||
dest = '%s.tpc'%mod
|
||||
if CLEAN or not os.path.exists(dest) or os.stat(src).st_mtime > os.stat(dest).st_mtime:
|
||||
cmd = cmd.replace('$SRC',src)
|
||||
cmd = cmd.replace('$DEST',dest)
|
||||
do_cmd(cmd)
|
||||
else:
|
||||
print '#',dest,'is up to date'
|
||||
|
||||
def build_gcc():
|
||||
mods = CORE[:]
|
||||
do_chdir(os.path.join(TOPDIR,'tinypy'))
|
||||
if TEST:
|
||||
mods.append('tests')
|
||||
do_cmd("gcc $WFLAGS -g vmmain.c $FLAGS -lm -o vm")
|
||||
do_cmd('python tests.py $SYS')
|
||||
for mod in mods:
|
||||
py2bc('python py2bc.py $SRC $DEST',mod)
|
||||
else:
|
||||
for mod in mods:
|
||||
py2bc('python py2bc.py $SRC $DEST -nopos',mod)
|
||||
if BOOT:
|
||||
do_cmd('$VM tests.tpc $SYS')
|
||||
for mod in mods: py2bc('$VM py2bc.tpc $SRC $DEST',mod)
|
||||
build_bc()
|
||||
do_cmd("gcc $WFLAGS -g tpmain.c $FLAGS -lm -o tinypy")
|
||||
#second pass - builts optimized binaries and stuff
|
||||
if BOOT:
|
||||
do_cmd('$TINYPY tests.py $SYS')
|
||||
for mod in mods: py2bc('$TINYPY py2bc.py $SRC $DEST -nopos',mod)
|
||||
build_bc(True)
|
||||
if BOOT:
|
||||
do_cmd("gcc $WFLAGS -O2 tpmain.c $FLAGS -lm -o tinypy")
|
||||
do_cmd('$TINYPY tests.py $SYS')
|
||||
print("# OK - we'll try -O3 for extra speed ...")
|
||||
do_cmd("gcc $WFLAGS -O3 tpmain.c $FLAGS -lm -o tinypy")
|
||||
do_cmd('$TINYPY tests.py $SYS')
|
||||
do_cmd("gcc $WFLAGS -O3 mymain.c $FLAGS -lm -o ../build/tinypy")
|
||||
do_chdir('..')
|
||||
if TEST:
|
||||
test_mods(os.path.join('.','build','tinypy')+' $TESTS')
|
||||
print("# OK")
|
||||
|
||||
def get_libs():
|
||||
modules = os.listdir('modules')
|
||||
for m in modules[:]:
|
||||
if m not in sys.argv: modules.remove(m)
|
||||
global MODULES
|
||||
MODULES = modules
|
||||
|
||||
def build_mymain():
|
||||
src = os.path.join(TOPDIR,'tinypy','tpmain.c')
|
||||
out = open(src,'r').read()
|
||||
dest = os.path.join(TOPDIR,'tinypy','mymain.c')
|
||||
|
||||
vs = []
|
||||
for m in MODULES:
|
||||
vs.append('#include "../modules/%s/init.c"'%m)
|
||||
out = out.replace('/* INCLUDE */','\n'.join(vs))
|
||||
|
||||
vs = []
|
||||
for m in MODULES:
|
||||
vs.append('%s_init(tp);'%m)
|
||||
out = out.replace('/* INIT */','\n'.join(vs))
|
||||
|
||||
f = open(dest,'w')
|
||||
f.write(out)
|
||||
f.close()
|
||||
return True
|
||||
|
||||
def test_mods(cmd):
|
||||
for m in MODULES:
|
||||
tests = os.path.join('modules',m,'tests.py')
|
||||
if not os.path.exists(tests): continue
|
||||
cmd = cmd.replace('$TESTS',tests)
|
||||
do_cmd(cmd)
|
||||
|
||||
def build_vs():
|
||||
# How to compile on windows with Visual Studio:
|
||||
# Call the batch script that sets environement variables for Visual Studio and
|
||||
# then run this script.
|
||||
# For VS 2005 the script is:
|
||||
# "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat"
|
||||
# For VS 2008: "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat"
|
||||
# Doesn't compile with vc6 (no variadic macros)
|
||||
# Note: /MD option causes to dynamically link with msvcrt80.dll. This dramatically
|
||||
# reduces size (for vm.exe 159k => 49k). Downside is that msvcrt80.dll must be
|
||||
# present on the system (and not all windows machine have it). You can either re-distribute
|
||||
# msvcrt80.dll or statically link with C runtime by changing /MD to /MT.
|
||||
mods = CORE[:]; mods.append('tests')
|
||||
os.chdir(os.path.join(TOPDIR,'tinypy'))
|
||||
do_cmd('cl vmmain.c /D "inline=" /Od /Zi /MD /Fdvm.pdb /Fmvm.map /Fevm.exe')
|
||||
do_cmd('python tests.py -win')
|
||||
for mod in mods: do_cmd('python py2bc.py %s.py %s.tpc'%(mod,mod))
|
||||
do_cmd('vm.exe tests.tpc -win')
|
||||
for mod in mods: do_cmd('vm.exe py2bc.tpc %s.py %s.tpc'%(mod,mod))
|
||||
build_bc()
|
||||
do_cmd('cl /Od tpmain.c /D "inline=" /Zi /MD /Fdtinypy.pdb /Fmtinypy.map /Fetinypy.exe')
|
||||
#second pass - builts optimized binaries and stuff
|
||||
do_cmd('tinypy.exe tests.py -win')
|
||||
for mod in mods: do_cmd('tinypy.exe py2bc.py %s.py %s.tpc -nopos'%(mod,mod))
|
||||
build_bc(True)
|
||||
do_cmd('cl /Os vmmain.c /D "inline=__inline" /D "NDEBUG" /Gy /GL /Zi /MD /Fdvm.pdb /Fmvm.map /Fevm.exe /link /opt:ref /opt:icf')
|
||||
do_cmd('cl /Os tpmain.c /D "inline=__inline" /D "NDEBUG" /Gy /GL /Zi /MD /Fdtinypy.pdb /Fmtinypy.map /Fetinypy.exe /link /opt:ref,icf /OPT:NOWIN98')
|
||||
do_cmd("tinypy.exe tests.py -win")
|
||||
do_cmd("dir *.exe")
|
||||
|
||||
def shrink(fname):
|
||||
f = open(fname,'r'); lines = f.readlines(); f.close()
|
||||
out = []
|
||||
fixes = [
|
||||
'vm','gc','params','STR',
|
||||
'int','float','return','free','delete','init',
|
||||
'abs','round','system','pow','div','raise','hash','index','printf','main']
|
||||
passing = False
|
||||
for line in lines:
|
||||
#quit if we've already converted
|
||||
if '\t' in line: return ''.join(lines)
|
||||
|
||||
#change " " into "\t" and remove blank lines
|
||||
if len(line.strip()) == 0: continue
|
||||
line = line.rstrip()
|
||||
l1,l2 = len(line),len(line.lstrip())
|
||||
line = "\t"*((l1-l2)/4)+line.lstrip()
|
||||
|
||||
#remove comments
|
||||
if '.c' in fname or '.h' in fname:
|
||||
#start block comment
|
||||
if line.strip()[:2] == '/*':
|
||||
passing = True;
|
||||
#end block comment
|
||||
if line.strip()[-2:] == '*/':
|
||||
passing = False;
|
||||
continue
|
||||
#skip lines inside block comments
|
||||
if passing:
|
||||
continue
|
||||
if '.py' in fname:
|
||||
if line.strip()[:1] == '#': continue
|
||||
|
||||
#remove the "namespace penalty" from tinypy ...
|
||||
for name in fixes:
|
||||
line = line.replace('TP_'+name,'t'+name)
|
||||
line = line.replace('tp_'+name,'t'+name)
|
||||
line = line.replace('TP_','')
|
||||
line = line.replace('tp_','')
|
||||
|
||||
out.append(line)
|
||||
return '\n'.join(out)+'\n'
|
||||
|
||||
def chksize():
|
||||
t1,t2 = 0,0
|
||||
for fname in [
|
||||
'tokenize.py','parse.py','encode.py','py2bc.py',
|
||||
'tp.h','list.c','dict.c','misc.c','string.c','builtins.c',
|
||||
'gc.c','ops.c','vm.c','tp.c','tpmain.c',
|
||||
]:
|
||||
fname = os.path.join(TOPDIR,'tinypy',fname)
|
||||
f = open(fname,'r'); t1 += len(f.read()); f.close()
|
||||
txt = shrink(fname)
|
||||
t2 += len(txt)
|
||||
print "#",t1,t2,t2-65536
|
||||
return t2
|
||||
|
||||
def build_64k():
|
||||
for fname in [
|
||||
'tokenize.py','parse.py','encode.py','py2bc.py',
|
||||
'tp.h','list.c','dict.c','misc.c','string.c','builtins.c',
|
||||
'gc.c','ops.c','vm.c','tp.c','tpmain.c',
|
||||
]:
|
||||
src = os.path.join(TOPDIR,'tinypy',fname)
|
||||
dest = os.path.join(TOPDIR,'build',fname)
|
||||
txt = shrink(src)
|
||||
f = open(dest,'w')
|
||||
f.write(txt)
|
||||
f.close()
|
||||
print '%s saved to %s'%(src,dest)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
7
programs/develop/tinypy/tinypy/Makefile
Normal file
7
programs/develop/tinypy/tinypy/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
export MENUETDEV=/home/john/Kolibri/kolibrios.org/libc
|
||||
OUTFILE = tpmain
|
||||
OBJS = tpmain.o
|
||||
include $(MENUETDEV)/makefiles/Makefile_for_program
|
||||
#testmod.o: fasm_modules/testmod.s
|
||||
# fasm fasm_modules/testmod.s
|
||||
# cp fasm_modules/testmod.o .
|
3805
programs/develop/tinypy/tinypy/bc.c
Normal file
3805
programs/develop/tinypy/tinypy/bc.c
Normal file
File diff suppressed because it is too large
Load Diff
46
programs/develop/tinypy/tinypy/boot.py
Normal file
46
programs/develop/tinypy/tinypy/boot.py
Normal file
@ -0,0 +1,46 @@
|
||||
def _boot_init():
|
||||
global FTYPE
|
||||
f = open('tp.h','r').read()
|
||||
FTYPE = 'f'
|
||||
if 'double tp_num' in f: FTYPE = 'd'
|
||||
import sys
|
||||
global ARGV
|
||||
ARGV = sys.argv
|
||||
_boot_init()
|
||||
|
||||
def merge(a,b):
|
||||
if isinstance(a,dict):
|
||||
for k in b: a[k] = b[k]
|
||||
else:
|
||||
for k in b: setattr(a,k,b[k])
|
||||
|
||||
def number(v):
|
||||
if type(v) is str and v[0:2] == '0x':
|
||||
v = int(v[2:],16)
|
||||
return float(v)
|
||||
|
||||
def istype(v,t):
|
||||
if t == 'string': return isinstance(v,str)
|
||||
elif t == 'list': return (isinstance(v,list) or isinstance(v,tuple))
|
||||
elif t == 'dict': return isinstance(v,dict)
|
||||
elif t == 'number': return (isinstance(v,float) or isinstance(v,int))
|
||||
raise '?'
|
||||
|
||||
def fpack(v):
|
||||
import struct
|
||||
return struct.pack(FTYPE,v)
|
||||
|
||||
def system(cmd):
|
||||
import os
|
||||
return os.system(cmd)
|
||||
|
||||
def load(fname):
|
||||
f = open(fname,'rb')
|
||||
r = f.read()
|
||||
f.close()
|
||||
return r
|
||||
|
||||
def save(fname,v):
|
||||
f = open(fname,'wb')
|
||||
f.write(v)
|
||||
f.close()
|
196
programs/develop/tinypy/tinypy/builtins.c
Normal file
196
programs/develop/tinypy/tinypy/builtins.c
Normal file
@ -0,0 +1,196 @@
|
||||
tp_obj tp_print(TP) {
|
||||
int n = 0;
|
||||
tp_obj e;
|
||||
TP_LOOP(e)
|
||||
if (n) { con_printf(" "); }
|
||||
con_printf("%s",TP_CSTR(e));
|
||||
n += 1;
|
||||
TP_END;
|
||||
con_printf("\n");
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
tp_obj tp_bind(TP) {
|
||||
tp_obj r = TP_OBJ();
|
||||
tp_obj self = TP_OBJ();
|
||||
return tp_fnc_new(tp,r.fnc.ftype|2,r.fnc.val,self,r.fnc.info->globals);
|
||||
}
|
||||
|
||||
tp_obj tp_min(TP) {
|
||||
tp_obj r = TP_OBJ();
|
||||
tp_obj e;
|
||||
TP_LOOP(e)
|
||||
if (tp_cmp(tp,r,e) > 0) { r = e; }
|
||||
TP_END;
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj tp_syscall(TP) {
|
||||
tp_obj r = TP_OBJ();
|
||||
int result;
|
||||
asm("int $0x40":"=a"(result):
|
||||
"a"((int)tp_get(tp, r, tp_string_n("eax", 3)).number.val),
|
||||
"b"((int)tp_get(tp, r, tp_string_n("ebx", 3)).number.val),
|
||||
"c"((int)tp_get(tp, r, tp_string_n("ecx", 3)).number.val),
|
||||
"d"((int)tp_get(tp, r, tp_string_n("edx", 3)).number.val));
|
||||
return tp_number(result);
|
||||
}
|
||||
|
||||
tp_obj tp_max(TP) {
|
||||
tp_obj r = TP_OBJ();
|
||||
tp_obj e;
|
||||
TP_LOOP(e)
|
||||
if (tp_cmp(tp,r,e) < 0) { r = e; }
|
||||
TP_END;
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj tp_copy(TP) {
|
||||
tp_obj r = TP_OBJ();
|
||||
int type = r.type;
|
||||
if (type == TP_LIST) {
|
||||
return _tp_list_copy(tp,r);
|
||||
} else if (type == TP_DICT) {
|
||||
return _tp_dict_copy(tp,r);
|
||||
}
|
||||
tp_raise(tp_None,"tp_copy(%s)",TP_CSTR(r));
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_len_(TP) {
|
||||
tp_obj e = TP_OBJ();
|
||||
return tp_len(tp,e);
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_assert(TP) {
|
||||
int a = TP_NUM();
|
||||
if (a) { return tp_None; }
|
||||
tp_raise(tp_None,"%s","assert failed");
|
||||
}
|
||||
|
||||
tp_obj tp_range(TP) {
|
||||
int a,b,c,i;
|
||||
tp_obj r = tp_list(tp);
|
||||
switch (tp->params.list.val->len) {
|
||||
case 1: a = 0; b = TP_NUM(); c = 1; break;
|
||||
case 2:
|
||||
case 3: a = TP_NUM(); b = TP_NUM(); c = TP_DEFAULT(tp_number(1)).number.val; break;
|
||||
default: return r;
|
||||
}
|
||||
if (c != 0) {
|
||||
for (i=a; (c>0) ? i<b : i>b; i+=c) {
|
||||
_tp_list_append(tp,r.list.val,tp_number(i));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_system(TP) {
|
||||
char const *s = TP_STR();
|
||||
int r = system(s);
|
||||
return tp_number(r);
|
||||
}
|
||||
|
||||
tp_obj tp_istype(TP) {
|
||||
tp_obj v = TP_OBJ();
|
||||
char const *t = TP_STR();
|
||||
if (strcmp("string",t) == 0) { return tp_number(v.type == TP_STRING); }
|
||||
if (strcmp("list",t) == 0) { return tp_number(v.type == TP_LIST); }
|
||||
if (strcmp("dict",t) == 0) { return tp_number(v.type == TP_DICT); }
|
||||
if (strcmp("number",t) == 0) { return tp_number(v.type == TP_NUMBER); }
|
||||
tp_raise(tp_None,"is_type(%s,%s)",TP_CSTR(v),t);
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_float(TP) {
|
||||
tp_obj v = TP_OBJ();
|
||||
int ord = TP_DEFAULT(tp_number(0)).number.val;
|
||||
int type = v.type;
|
||||
if (type == TP_NUMBER) { return v; }
|
||||
if (type == TP_STRING) {
|
||||
if (strchr(TP_CSTR(v),'.')) { return tp_number(atof(TP_CSTR(v))); }
|
||||
return(tp_number(strtol(TP_CSTR(v),0,ord)));
|
||||
}
|
||||
tp_raise(tp_None,"tp_float(%s)",TP_CSTR(v));
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_save(TP) {
|
||||
char const *fname = TP_STR();
|
||||
tp_obj v = TP_OBJ();
|
||||
FILE *f;
|
||||
f = fopen(fname,"wb");
|
||||
if (!f) { tp_raise(tp_None,"tp_save(%s,...)",fname); }
|
||||
fwrite(v.string.val,v.string.len,1,f);
|
||||
fclose(f);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
#define READ_BLK 1024
|
||||
tp_obj tp_load(TP) {
|
||||
FILE *f;
|
||||
long l = 0;
|
||||
tp_obj r;
|
||||
char *s;
|
||||
char const *fname = TP_STR();
|
||||
long rd = 0;
|
||||
long allocated = 32 * READ_BLK;
|
||||
|
||||
|
||||
if (!(f = fopen(fname, "rb"))) {
|
||||
tp_raise(tp_None,"tp_load(%s)",fname);
|
||||
}
|
||||
if (!(s = malloc(allocated)))
|
||||
tp_raise(tp_None, "tp_load(%s): out of memory", fname);
|
||||
rd = 0;
|
||||
do {
|
||||
if (l + READ_BLK < allocated) {
|
||||
allocated += READ_BLK;
|
||||
if (!(s = realloc(s, allocated))) {
|
||||
tp_raise(tp_None, "tp_load(%s): out of memory", fname);
|
||||
}
|
||||
}
|
||||
rd = fread(s + l, 1, READ_BLK, f);
|
||||
l += rd;
|
||||
} while (rd == READ_BLK);
|
||||
r = tp_string_n(s, l);
|
||||
fclose(f);
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_fpack(TP) {
|
||||
tp_num v = TP_NUM();
|
||||
tp_obj r = tp_string_t(tp,sizeof(tp_num));
|
||||
*(tp_num*)r.string.val = v;
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
tp_obj tp_abs(TP) {
|
||||
return tp_number(fabs(tp_float(tp).number.val));
|
||||
}
|
||||
tp_obj tp_int(TP) {
|
||||
return tp_number((long)tp_float(tp).number.val);
|
||||
}
|
||||
tp_num _roundf(tp_num v) {
|
||||
tp_num av = fabs(v); tp_num iv = (long)av;
|
||||
av = (av-iv < 0.5?iv:iv+1);
|
||||
return (v<0?-av:av);
|
||||
}
|
||||
tp_obj tp_round(TP) {
|
||||
return tp_number(_roundf(tp_float(tp).number.val));
|
||||
}
|
||||
|
||||
tp_obj tp_exists(TP) {
|
||||
char const *s = TP_STR();
|
||||
struct stat stbuf;
|
||||
return tp_number(!stat(s,&stbuf));
|
||||
}
|
||||
tp_obj tp_mtime(TP) {
|
||||
char const *s = TP_STR();
|
||||
struct stat stbuf;
|
||||
if (!stat(s,&stbuf)) { return tp_number(stbuf.st_mtime); }
|
||||
tp_raise(tp_None,"tp_mtime(%s)",s);
|
||||
}
|
169
programs/develop/tinypy/tinypy/dict.c
Normal file
169
programs/develop/tinypy/tinypy/dict.c
Normal file
@ -0,0 +1,169 @@
|
||||
int tp_lua_hash(void const *v,int l) {
|
||||
int i,step = (l>>5)+1;
|
||||
int h = l + (l >= 4?*(int*)v:0);
|
||||
for (i=l; i>=step; i-=step) {
|
||||
h = h^((h<<5)+(h>>2)+((unsigned char *)v)[i-1]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
void _tp_dict_free(_tp_dict *self) {
|
||||
tp_free(self->items);
|
||||
tp_free(self);
|
||||
}
|
||||
|
||||
/* void _tp_dict_reset(_tp_dict *self) {
|
||||
memset(self->items,0,self->alloc*sizeof(tp_item));
|
||||
self->len = 0;
|
||||
self->used = 0;
|
||||
self->cur = 0;
|
||||
}*/
|
||||
|
||||
int tp_hash(TP,tp_obj v) {
|
||||
switch (v.type) {
|
||||
case TP_NONE: return 0;
|
||||
case TP_NUMBER: return tp_lua_hash(&v.number.val,sizeof(tp_num));
|
||||
case TP_STRING: return tp_lua_hash(v.string.val,v.string.len);
|
||||
case TP_DICT: return tp_lua_hash(&v.dict.val,sizeof(void*));
|
||||
case TP_LIST: {
|
||||
int r = v.list.val->len; int n; for(n=0; n<v.list.val->len; n++) {
|
||||
tp_obj vv = v.list.val->items[n]; r += vv.type != TP_LIST?tp_hash(tp,v.list.val->items[n]):tp_lua_hash(&vv.list.val,sizeof(void*)); } return r;
|
||||
}
|
||||
case TP_FNC: return tp_lua_hash(&v.fnc.info,sizeof(void*));
|
||||
case TP_DATA: return tp_lua_hash(&v.data.val,sizeof(void*));
|
||||
}
|
||||
tp_raise(0,"tp_hash(%s)",TP_CSTR(v));
|
||||
}
|
||||
|
||||
void _tp_dict_hash_set(TP,_tp_dict *self, int hash, tp_obj k, tp_obj v) {
|
||||
tp_item item;
|
||||
int i,idx = hash&self->mask;
|
||||
for (i=idx; i<idx+self->alloc; i++) {
|
||||
int n = i&self->mask;
|
||||
if (self->items[n].used > 0) { continue; }
|
||||
if (self->items[n].used == 0) { self->used += 1; }
|
||||
item.used = 1;
|
||||
item.hash = hash;
|
||||
item.key = k;
|
||||
item.val = v;
|
||||
self->items[n] = item;
|
||||
self->len += 1;
|
||||
return;
|
||||
}
|
||||
tp_raise(,"_tp_dict_hash_set(%d,%d,%s,%s)",self,hash,TP_CSTR(k),TP_CSTR(v));
|
||||
}
|
||||
|
||||
void _tp_dict_tp_realloc(TP,_tp_dict *self,int len) {
|
||||
tp_item *items = self->items;
|
||||
int i,alloc = self->alloc;
|
||||
len = _tp_max(8,len);
|
||||
|
||||
self->items = (tp_item*)tp_malloc(len*sizeof(tp_item));
|
||||
self->alloc = len; self->mask = len-1;
|
||||
self->len = 0; self->used = 0;
|
||||
|
||||
for (i=0; i<alloc; i++) {
|
||||
if (items[i].used != 1) { continue; }
|
||||
_tp_dict_hash_set(tp,self,items[i].hash,items[i].key,items[i].val);
|
||||
}
|
||||
tp_free(items);
|
||||
}
|
||||
|
||||
int _tp_dict_hash_find(TP,_tp_dict *self, int hash, tp_obj k) {
|
||||
int i,idx = hash&self->mask;
|
||||
for (i=idx; i<idx+self->alloc; i++) {
|
||||
int n = i&self->mask;
|
||||
if (self->items[n].used == 0) { break; }
|
||||
if (self->items[n].used < 0) { continue; }
|
||||
if (self->items[n].hash != hash) { continue; }
|
||||
if (tp_cmp(tp,self->items[n].key,k) != 0) { continue; }
|
||||
return n;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int _tp_dict_find(TP,_tp_dict *self,tp_obj k) {
|
||||
return _tp_dict_hash_find(tp,self,tp_hash(tp,k),k);
|
||||
}
|
||||
|
||||
void _tp_dict_setx(TP,_tp_dict *self,tp_obj k, tp_obj v) {
|
||||
int hash = tp_hash(tp,k); int n = _tp_dict_hash_find(tp,self,hash,k);
|
||||
if (n == -1) {
|
||||
if (self->len >= (self->alloc/2)) {
|
||||
_tp_dict_tp_realloc(tp,self,self->alloc*2);
|
||||
} else if (self->used >= (self->alloc*3/4)) {
|
||||
_tp_dict_tp_realloc(tp,self,self->alloc);
|
||||
}
|
||||
_tp_dict_hash_set(tp,self,hash,k,v);
|
||||
} else {
|
||||
self->items[n].val = v;
|
||||
}
|
||||
}
|
||||
|
||||
void _tp_dict_set(TP,_tp_dict *self,tp_obj k, tp_obj v) {
|
||||
_tp_dict_setx(tp,self,k,v);
|
||||
tp_grey(tp,k); tp_grey(tp,v);
|
||||
}
|
||||
|
||||
tp_obj _tp_dict_get(TP,_tp_dict *self,tp_obj k, const char *error) {
|
||||
int n = _tp_dict_find(tp,self,k);
|
||||
if (n < 0) {
|
||||
tp_raise(tp_None,"%s: KeyError: %s\n",error,TP_CSTR(k));
|
||||
}
|
||||
return self->items[n].val;
|
||||
}
|
||||
|
||||
void _tp_dict_del(TP,_tp_dict *self,tp_obj k, const char *error) {
|
||||
int n = _tp_dict_find(tp,self,k);
|
||||
if (n < 0) { tp_raise(,"%s: KeyError: %s\n",error,TP_CSTR(k)); }
|
||||
self->items[n].used = -1;
|
||||
self->len -= 1;
|
||||
}
|
||||
|
||||
_tp_dict *_tp_dict_new(void) {
|
||||
_tp_dict *self = (_tp_dict*)tp_malloc(sizeof(_tp_dict));
|
||||
return self;
|
||||
}
|
||||
tp_obj _tp_dict_copy(TP,tp_obj rr) {
|
||||
tp_obj obj = {TP_DICT};
|
||||
_tp_dict *o = rr.dict.val;
|
||||
_tp_dict *r = _tp_dict_new();
|
||||
*r = *o; r->gci = 0;
|
||||
r->items = (tp_item*)tp_malloc(sizeof(tp_item)*o->alloc);
|
||||
memcpy(r->items,o->items,sizeof(tp_item)*o->alloc);
|
||||
obj.dict.val = r;
|
||||
return tp_track(tp,obj);
|
||||
}
|
||||
|
||||
int _tp_dict_next(TP,_tp_dict *self) {
|
||||
if (!self->len) { tp_raise(0,"_tp_dict_next(...)",0); }
|
||||
while (1) {
|
||||
self->cur = ((self->cur + 1) & self->mask);
|
||||
if (self->items[self->cur].used > 0) {
|
||||
return self->cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tp_obj tp_merge(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
int i; for (i=0; i<v.dict.val->len; i++) {
|
||||
int n = _tp_dict_next(tp,v.dict.val);
|
||||
_tp_dict_set(tp,self.dict.val,
|
||||
v.dict.val->items[n].key,v.dict.val->items[n].val);
|
||||
}
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
volatile tp_obj tp_dict(TP) {
|
||||
tp_obj r = {TP_DICT};
|
||||
r.dict.val = _tp_dict_new();
|
||||
return tp ? tp_track(tp,r) : r;
|
||||
}
|
||||
|
||||
tp_obj tp_dict_n(TP,int n, tp_obj* argv) {
|
||||
tp_obj r = tp_dict(tp);
|
||||
int i; for (i=0; i<n; i++) { tp_set(tp,r,argv[i*2],argv[i*2+1]); }
|
||||
return r;
|
||||
}
|
||||
|
||||
|
699
programs/develop/tinypy/tinypy/encode.py
Normal file
699
programs/develop/tinypy/tinypy/encode.py
Normal file
@ -0,0 +1,699 @@
|
||||
import tokenize
|
||||
from tokenize import Token
|
||||
if '.' in str(1.0):
|
||||
from boot import *
|
||||
|
||||
EOF,ADD,SUB,MUL,DIV,POW,AND,OR,CMP,GET,SET,NUMBER,STRING,GGET,GSET,MOVE,DEF,PASS,JUMP,CALL,RETURN,IF,DEBUG,EQ,LE,LT,DICT,LIST,NONE,LEN,POS,PARAMS,IGET,FILE,NAME,NE,HAS,RAISE,SETJMP,MOD,LSH,RSH,ITER,DEL,REGS = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44
|
||||
|
||||
class DState:
|
||||
def __init__(self,code,fname):
|
||||
self.code, self.fname = code,fname
|
||||
self.lines = self.code.split('\n')
|
||||
|
||||
self.stack,self.out,self._scopei,self.tstack,self._tagi,self.data = [],[('tag','EOF')],0,[],0,{}
|
||||
self.error = False
|
||||
def begin(self,gbl=False):
|
||||
if len(self.stack): self.stack.append((self.vars,self.r2n,self.n2r,self._tmpi,self.mreg,self.snum,self._globals,self.lineno,self.globals,self.cregs,self.tmpc))
|
||||
else: self.stack.append(None)
|
||||
self.vars,self.r2n,self.n2r,self._tmpi,self.mreg,self.snum,self._globals,self.lineno,self.globals,self.cregs,self.tmpc = [],{},{},0,0,str(self._scopei),gbl,-1,[],['regs'],0
|
||||
self._scopei += 1
|
||||
insert(self.cregs)
|
||||
def end(self):
|
||||
self.cregs.append(self.mreg)
|
||||
code(EOF)
|
||||
|
||||
# This next line forces the encoder to
|
||||
# throw an exception if any tmp regs
|
||||
# were leaked within the frame
|
||||
assert(self.tmpc == 0) #REG
|
||||
|
||||
if len(self.stack) > 1:
|
||||
self.vars,self.r2n,self.n2r,self._tmpi,self.mreg,self.snum,self._globals,self.lineno,self.globals,self.cregs,self.tmpc = self.stack.pop()
|
||||
else: self.stack.pop()
|
||||
|
||||
|
||||
def insert(v): D.out.append(v)
|
||||
def write(v):
|
||||
if istype(v,'list'):
|
||||
insert(v)
|
||||
return
|
||||
for n in range(0,len(v),4):
|
||||
insert(('data',v[n:n+4]))
|
||||
def setpos(v):
|
||||
if '-nopos' in ARGV: return
|
||||
line,x = v
|
||||
if line == D.lineno: return
|
||||
text = D.lines[line-1]
|
||||
D.lineno = line
|
||||
val = text + "\0"*(4-len(text)%4)
|
||||
code_16(POS,len(val)/4,line)
|
||||
write(val)
|
||||
def code(i,a=0,b=0,c=0):
|
||||
if not istype(i,'number'): raise
|
||||
if not istype(a,'number'): raise
|
||||
if not istype(b,'number'): raise
|
||||
if not istype(c,'number'): raise
|
||||
write(('code',i,a,b,c))
|
||||
def code_16(i,a,b):
|
||||
if b < 0: b += 0x8000
|
||||
code(i,a,(b&0xff00)>>8,(b&0xff)>>0)
|
||||
def get_code16(i,a,b):
|
||||
return ('code',i,a,(b&0xff00)>>8,(b&0xff)>>0)
|
||||
|
||||
def _do_string(v,r=None):
|
||||
r = get_tmp(r)
|
||||
val = v + "\0"*(4-len(v)%4)
|
||||
code_16(STRING,r,len(v))
|
||||
write(val)
|
||||
return r
|
||||
def do_string(t,r=None):
|
||||
return _do_string(t.val,r)
|
||||
|
||||
def _do_number(v,r=None):
|
||||
r = get_tmp(r)
|
||||
code(NUMBER,r,0,0)
|
||||
write(fpack(number(v)))
|
||||
return r
|
||||
def do_number(t,r=None):
|
||||
return _do_number(t.val,r)
|
||||
|
||||
def get_tag():
|
||||
k = str(D._tagi)
|
||||
D._tagi += 1
|
||||
return k
|
||||
def stack_tag():
|
||||
k = get_tag()
|
||||
D.tstack.append(k)
|
||||
return k
|
||||
def pop_tag():
|
||||
D.tstack.pop()
|
||||
|
||||
def tag(*t):
|
||||
t = D.snum+':'+':'.join([str(v) for v in t])
|
||||
insert(('tag',t))
|
||||
def jump(*t):
|
||||
t = D.snum+':'+':'.join([str(v) for v in t])
|
||||
insert(('jump',t))
|
||||
def setjmp(*t):
|
||||
t = D.snum+':'+':'.join([str(v) for v in t])
|
||||
insert(('setjmp',t))
|
||||
def fnc(*t):
|
||||
t = D.snum+':'+':'.join([str(v) for v in t])
|
||||
r = get_reg(t)
|
||||
insert(('fnc',r,t))
|
||||
return r
|
||||
|
||||
def map_tags():
|
||||
tags = {}
|
||||
out = []
|
||||
n = 0
|
||||
for item in D.out:
|
||||
if item[0] == 'tag':
|
||||
tags[item[1]] = n
|
||||
continue
|
||||
if item[0] == 'regs':
|
||||
out.append(get_code16(REGS,item[1],0))
|
||||
n += 1
|
||||
continue
|
||||
out.append(item)
|
||||
n += 1
|
||||
for n in range(0,len(out)):
|
||||
item = out[n]
|
||||
if item[0] == 'jump':
|
||||
out[n] = get_code16(JUMP,0,tags[item[1]]-n)
|
||||
elif item[0] == 'setjmp':
|
||||
out[n] = get_code16(SETJMP,0,tags[item[1]]-n)
|
||||
elif item[0] == 'fnc':
|
||||
out[n] = get_code16(DEF,item[1],tags[item[2]]-n)
|
||||
for n in range(0,len(out)):
|
||||
item = out[n]
|
||||
if item[0] == 'data':
|
||||
out[n] = item[1]
|
||||
elif item[0] == 'code':
|
||||
i,a,b,c = item[1:]
|
||||
out[n] = chr(i)+chr(a)+chr(b)+chr(c)
|
||||
else:
|
||||
raise str(('huh?',item))
|
||||
if len(out[n]) != 4:
|
||||
raise ('code '+str(n)+' is wrong length '+str(len(out[n])))
|
||||
D.out = out
|
||||
|
||||
def get_tmp(r=None):
|
||||
if r != None: return r
|
||||
return get_tmps(1)[0]
|
||||
def get_tmps(t):
|
||||
rs = alloc(t)
|
||||
regs = range(rs,rs+t)
|
||||
for r in regs:
|
||||
set_reg(r,"$"+str(D._tmpi))
|
||||
D._tmpi += 1
|
||||
D.tmpc += t #REG
|
||||
return regs
|
||||
def alloc(t):
|
||||
s = ''.join(["01"[r in D.r2n] for r in range(0,min(256,D.mreg+t))])
|
||||
return s.index('0'*t)
|
||||
def is_tmp(r):
|
||||
if r is None: return False
|
||||
return (D.r2n[r][0] == '$')
|
||||
def un_tmp(r):
|
||||
n = D.r2n[r]
|
||||
free_reg(r)
|
||||
set_reg(r,'*'+n)
|
||||
def free_tmp(r):
|
||||
if is_tmp(r): free_reg(r)
|
||||
return r
|
||||
def free_tmps(r):
|
||||
for k in r: free_tmp(k)
|
||||
def get_reg(n):
|
||||
if n not in D.n2r:
|
||||
set_reg(alloc(1),n)
|
||||
return D.n2r[n]
|
||||
#def get_clean_reg(n):
|
||||
#if n in D.n2r: raise
|
||||
#set_reg(D.mreg,n)
|
||||
#return D.n2r[n]
|
||||
def set_reg(r,n):
|
||||
D.n2r[n] = r; D.r2n[r] = n
|
||||
D.mreg = max(D.mreg,r+1)
|
||||
def free_reg(r):
|
||||
if is_tmp(r): D.tmpc -= 1
|
||||
n = D.r2n[r]; del D.r2n[r]; del D.n2r[n]
|
||||
|
||||
def imanage(orig,fnc):
|
||||
items = orig.items
|
||||
orig.val = orig.val[:-1]
|
||||
t = Token(orig.pos,'symbol','=',[items[0],orig])
|
||||
return fnc(t)
|
||||
|
||||
def infix(i,tb,tc,r=None):
|
||||
r = get_tmp(r)
|
||||
b,c = do(tb,r),do(tc)
|
||||
code(i,r,b,c)
|
||||
if r != b: free_tmp(b)
|
||||
free_tmp(c)
|
||||
return r
|
||||
def ss_infix(ss,i,tb,tc,r=None):
|
||||
r = get_tmp(r)
|
||||
r2 = get_tmp()
|
||||
ss = _do_number(ss)
|
||||
t = get_tag()
|
||||
r = do(tb,r)
|
||||
code(EQ,r2,r,ss)
|
||||
code(IF,r2)
|
||||
jump(t,'else')
|
||||
jump(t,'end')
|
||||
tag(t,'else')
|
||||
r = do(tc,r)
|
||||
tag(t,'end')
|
||||
free_tmp(r2) #REG
|
||||
free_tmp(ss) #REG
|
||||
return r
|
||||
|
||||
def _do_none(r=None):
|
||||
r = get_tmp(r)
|
||||
code(NONE,r)
|
||||
return r
|
||||
|
||||
def do_symbol(t,r=None):
|
||||
sets = ['=']
|
||||
isets = ['+=','-=','*=','/=']
|
||||
cmps = ['<','>','<=','>=','==','!=']
|
||||
metas = {
|
||||
'+':ADD,'*':MUL,'/':DIV,'**':POW,
|
||||
'-':SUB,'and':AND,'or':OR,
|
||||
'%':MOD,'>>':RSH,'<<':LSH,
|
||||
'&':AND,'|':OR,
|
||||
}
|
||||
if t.val == 'None': return _do_none(r)
|
||||
if t.val == 'True':
|
||||
return _do_number('1',r)
|
||||
if t.val == 'False':
|
||||
return _do_number('0',r)
|
||||
items = t.items
|
||||
|
||||
if t.val in ['and','or']:
|
||||
ss = int(t.val == 'or')
|
||||
return ss_infix(ss,metas[t.val],items[0],items[1],r)
|
||||
if t.val in isets:
|
||||
return imanage(t,do_symbol)
|
||||
if t.val == 'is':
|
||||
return infix(EQ,items[0],items[1],r)
|
||||
if t.val == 'isnot':
|
||||
return infix(CMP,items[0],items[1],r)
|
||||
if t.val == 'not':
|
||||
return infix(EQ,Token(t.pos,'number',0),items[0],r)
|
||||
if t.val == 'in':
|
||||
return infix(HAS,items[1],items[0],r)
|
||||
if t.val == 'notin':
|
||||
r = infix(HAS,items[1],items[0],r)
|
||||
zero = _do_number('0')
|
||||
code(EQ,r,r,free_tmp(zero))
|
||||
return r
|
||||
if t.val in sets:
|
||||
return do_set_ctx(items[0],items[1]);
|
||||
elif t.val in cmps:
|
||||
b,c = items[0],items[1]
|
||||
v = t.val
|
||||
if v[0] in ('>','>='):
|
||||
b,c,v = c,b,'<'+v[1:]
|
||||
cd = EQ
|
||||
if v == '<': cd = LT
|
||||
if v == '<=': cd = LE
|
||||
if v == '!=': cd = NE
|
||||
return infix(cd,b,c,r)
|
||||
else:
|
||||
return infix(metas[t.val],items[0],items[1],r)
|
||||
|
||||
def do_set_ctx(k,v):
|
||||
if k.type == 'name':
|
||||
if (D._globals and k.val not in D.vars) or (k.val in D.globals):
|
||||
c = do_string(k)
|
||||
b = do(v)
|
||||
code(GSET,c,b)
|
||||
free_tmp(c)
|
||||
free_tmp(b)
|
||||
return
|
||||
a = do_local(k)
|
||||
b = do(v)
|
||||
code(MOVE,a,b)
|
||||
free_tmp(b)
|
||||
return a
|
||||
elif k.type in ('tuple','list'):
|
||||
if v.type in ('tuple','list'):
|
||||
n,tmps = 0,[]
|
||||
for kk in k.items:
|
||||
vv = v.items[n]
|
||||
tmp = get_tmp(); tmps.append(tmp)
|
||||
r = do(vv)
|
||||
code(MOVE,tmp,r)
|
||||
free_tmp(r) #REG
|
||||
n+=1
|
||||
n = 0
|
||||
for kk in k.items:
|
||||
vv = v.items[n]
|
||||
tmp = tmps[n]
|
||||
free_tmp(do_set_ctx(kk,Token(vv.pos,'reg',tmp))) #REG
|
||||
n += 1
|
||||
return
|
||||
|
||||
r = do(v); un_tmp(r)
|
||||
n, tmp = 0, Token(v.pos,'reg',r)
|
||||
for tt in k.items:
|
||||
free_tmp(do_set_ctx(tt,Token(tmp.pos,'get',None,[tmp,Token(tmp.pos,'number',str(n))]))) #REG
|
||||
n += 1
|
||||
free_reg(r)
|
||||
return
|
||||
r = do(k.items[0])
|
||||
rr = do(v)
|
||||
tmp = do(k.items[1])
|
||||
code(SET,r,tmp,rr)
|
||||
free_tmp(r) #REG
|
||||
free_tmp(tmp) #REG
|
||||
return rr
|
||||
|
||||
def manage_seq(i,a,items,sav=0):
|
||||
l = max(sav,len(items))
|
||||
n,tmps = 0,get_tmps(l)
|
||||
for tt in items:
|
||||
r = tmps[n]
|
||||
b = do(tt,r)
|
||||
if r != b:
|
||||
code(MOVE,r,b)
|
||||
free_tmp(b)
|
||||
n +=1
|
||||
if not len(tmps):
|
||||
code(i,a,0,0)
|
||||
return 0
|
||||
code(i,a,tmps[0],len(items))
|
||||
free_tmps(tmps[sav:])
|
||||
return tmps[0]
|
||||
|
||||
def p_filter(items):
|
||||
a,b,c,d = [],[],None,None
|
||||
for t in items:
|
||||
if t.type == 'symbol' and t.val == '=': b.append(t)
|
||||
elif t.type == 'args': c = t
|
||||
elif t.type == 'nargs': d = t
|
||||
else: a.append(t)
|
||||
return a,b,c,d
|
||||
|
||||
def do_import(t):
|
||||
for mod in t.items:
|
||||
mod.type = 'string'
|
||||
v = do_call(Token(t.pos,'call',None,[
|
||||
Token(t.pos,'name','import'),
|
||||
mod]))
|
||||
mod.type = 'name'
|
||||
do_set_ctx(mod,Token(t.pos,'reg',v))
|
||||
def do_from(t):
|
||||
mod = t.items[0]
|
||||
mod.type = 'string'
|
||||
v = do(Token(t.pos,'call',None,[
|
||||
Token(t.pos,'name','import'),
|
||||
mod]))
|
||||
item = t.items[1]
|
||||
if item.val == '*':
|
||||
free_tmp(do(Token(t.pos,'call',None,[
|
||||
Token(t.pos,'name','merge'),
|
||||
Token(t.pos,'name','__dict__'),
|
||||
Token(t.pos,'reg',v)]))) #REG
|
||||
else:
|
||||
item.type = 'string'
|
||||
free_tmp(do_set_ctx(
|
||||
Token(t.pos,'get',None,[ Token(t.pos,'name','__dict__'),item]),
|
||||
Token(t.pos,'get',None,[ Token(t.pos,'reg',v),item])
|
||||
)) #REG
|
||||
|
||||
|
||||
def do_globals(t):
|
||||
for t in t.items:
|
||||
if t.val not in D.globals:
|
||||
D.globals.append(t.val)
|
||||
def do_del(tt):
|
||||
for t in tt.items:
|
||||
r = do(t.items[0])
|
||||
r2 = do(t.items[1])
|
||||
code(DEL,r,r2)
|
||||
free_tmp(r); free_tmp(r2) #REG
|
||||
|
||||
def do_call(t,r=None):
|
||||
r = get_tmp(r)
|
||||
items = t.items
|
||||
fnc = do(items[0])
|
||||
a,b,c,d = p_filter(t.items[1:])
|
||||
e = None
|
||||
if len(b) != 0 or d != None:
|
||||
e = do(Token(t.pos,'dict',None,[])); un_tmp(e);
|
||||
for p in b:
|
||||
p.items[0].type = 'string'
|
||||
t1,t2 = do(p.items[0]),do(p.items[1])
|
||||
code(SET,e,t1,t2)
|
||||
free_tmp(t1); free_tmp(t2) #REG
|
||||
if d: free_tmp(do(Token(t.pos,'call',None,[Token(t.pos,'name','merge'),Token(t.pos,'reg',e),d.items[0]]))) #REG
|
||||
manage_seq(PARAMS,r,a)
|
||||
if c != None:
|
||||
t1,t2 = _do_string('*'),do(c.items[0])
|
||||
code(SET,r,t1,t2)
|
||||
free_tmp(t1); free_tmp(t2) #REG
|
||||
if e != None:
|
||||
t1 = _do_none()
|
||||
code(SET,r,t1,e)
|
||||
free_tmp(t1) #REG
|
||||
code(CALL,r,fnc,r)
|
||||
free_tmp(fnc) #REG
|
||||
return r
|
||||
|
||||
def do_name(t,r=None):
|
||||
if t.val in D.vars:
|
||||
return do_local(t,r)
|
||||
r = get_tmp(r)
|
||||
c = do_string(t)
|
||||
code(GGET,r,c)
|
||||
free_tmp(c)
|
||||
return r
|
||||
|
||||
def do_local(t,r=None):
|
||||
if t.val not in D.vars:
|
||||
D.vars.append(t.val)
|
||||
return get_reg(t.val)
|
||||
|
||||
def do_def(tok,kls=None):
|
||||
items = tok.items
|
||||
|
||||
t = get_tag()
|
||||
rf = fnc(t,'end')
|
||||
|
||||
D.begin()
|
||||
setpos(tok.pos)
|
||||
r = do_local(Token(tok.pos,'name','__params'))
|
||||
do_info(items[0].val)
|
||||
a,b,c,d = p_filter(items[1].items)
|
||||
for p in a:
|
||||
v = do_local(p)
|
||||
tmp = _do_none()
|
||||
code(GET,v,r,tmp)
|
||||
free_tmp(tmp) #REG
|
||||
for p in b:
|
||||
v = do_local(p.items[0])
|
||||
do(p.items[1],v)
|
||||
tmp = _do_none()
|
||||
code(IGET,v,r,tmp)
|
||||
free_tmp(tmp) #REG
|
||||
if c != None:
|
||||
v = do_local(c.items[0])
|
||||
tmp = _do_string('*')
|
||||
code(GET,v,r,tmp)
|
||||
free_tmp(tmp) #REG
|
||||
if d != None:
|
||||
e = do_local(d.items[0])
|
||||
code(DICT,e,0,0)
|
||||
tmp = _do_none()
|
||||
code(IGET,e,r,tmp)
|
||||
free_tmp(tmp) #REG
|
||||
free_tmp(do(items[2])) #REG
|
||||
D.end()
|
||||
|
||||
tag(t,'end')
|
||||
|
||||
if kls == None:
|
||||
if D._globals: do_globals(Token(tok.pos,0,0,[items[0]]))
|
||||
r = do_set_ctx(items[0],Token(tok.pos,'reg',rf))
|
||||
else:
|
||||
rn = do_string(items[0])
|
||||
code(SET,kls,rn,rf)
|
||||
free_tmp(rn)
|
||||
|
||||
free_tmp(rf)
|
||||
|
||||
def do_class(t):
|
||||
tok = t
|
||||
items = t.items
|
||||
parent = None
|
||||
if items[0].type == 'name':
|
||||
name = items[0].val
|
||||
else:
|
||||
name = items[0].items[0].val
|
||||
parent = items[0].items[1].val
|
||||
|
||||
kls = do(Token(t.pos,'dict',0,[]))
|
||||
ts = _do_string(name)
|
||||
code(GSET,ts,kls)
|
||||
free_tmp(ts) #REG
|
||||
|
||||
init,_new = False,[]
|
||||
if parent:
|
||||
_new.append(Token(t.pos,'call',None,[
|
||||
Token(t.pos,'get',None,[
|
||||
Token(t.pos,'name',parent),
|
||||
Token(t.pos,'string','__new__'),
|
||||
]),
|
||||
Token(t.pos,'name','self'),
|
||||
]))
|
||||
|
||||
for fc in items[1].items:
|
||||
if fc.type != 'def': continue
|
||||
fn = fc.items[0].val
|
||||
if fn == '__init__': init = True
|
||||
do_def(fc,kls)
|
||||
_new.append(Token(fc.pos,'symbol','=',[
|
||||
Token(fc.pos,'get',None,[
|
||||
Token(fc.pos,'name','self'),
|
||||
Token(fc.pos,'string',fn)]),
|
||||
Token(fc.pos,'call',None,[
|
||||
Token(fc.pos,'name','bind'),
|
||||
Token(fc.pos,'get',None,[
|
||||
Token(fc.pos,'name',name),
|
||||
Token(fc.pos,'string',fn)]),
|
||||
Token(fc.pos,'name','self')])
|
||||
]))
|
||||
|
||||
do_def(Token(t.pos,'def',None,[
|
||||
Token(t.pos,'name','__new__'),
|
||||
Token(t.pos,'list',None,[Token(t.pos,'name','self')]),
|
||||
Token(t.pos,'statements',None,_new)]),kls)
|
||||
|
||||
t = get_tag()
|
||||
rf = fnc(t,'end')
|
||||
D.begin()
|
||||
params = do_local(Token(tok.pos,'name','__params'))
|
||||
|
||||
slf = do_local(Token(tok.pos,'name','self'))
|
||||
code(DICT,slf,0,0)
|
||||
|
||||
free_tmp(do(Token(tok.pos,'call',None,[
|
||||
Token(tok.pos,'get',None,[
|
||||
Token(tok.pos,'name',name),
|
||||
Token(tok.pos,'string','__new__')]),
|
||||
Token(tok.pos,'name','self')]))) #REG
|
||||
|
||||
if init:
|
||||
tmp = get_tmp()
|
||||
t3 = _do_string('__init__')
|
||||
code(GET,tmp,slf,t3)
|
||||
t4 = get_tmp()
|
||||
code(CALL,t4,tmp,params)
|
||||
free_tmp(tmp) #REG
|
||||
free_tmp(t3) #REG
|
||||
free_tmp(t4) #REG
|
||||
code(RETURN,slf)
|
||||
|
||||
D.end()
|
||||
tag(t,'end')
|
||||
ts = _do_string('__call__')
|
||||
code(SET,kls,ts,rf)
|
||||
free_tmp(kls) #REG
|
||||
free_tmp(ts) #REG
|
||||
|
||||
|
||||
|
||||
|
||||
def do_while(t):
|
||||
items = t.items
|
||||
t = stack_tag()
|
||||
tag(t,'begin')
|
||||
tag(t,'continue')
|
||||
r = do(items[0])
|
||||
code(IF,r)
|
||||
free_tmp(r) #REG
|
||||
jump(t,'end')
|
||||
free_tmp(do(items[1])) #REG
|
||||
jump(t,'begin')
|
||||
tag(t,'break')
|
||||
tag(t,'end')
|
||||
pop_tag()
|
||||
|
||||
def do_for(tok):
|
||||
items = tok.items
|
||||
|
||||
reg = do_local(items[0])
|
||||
itr = do(items[1])
|
||||
i = _do_number('0')
|
||||
|
||||
t = stack_tag(); tag(t,'loop'); tag(t,'continue')
|
||||
code(ITER,reg,itr,i); jump(t,'end')
|
||||
free_tmp(do(items[2])) #REG
|
||||
jump(t,'loop')
|
||||
tag(t,'break'); tag(t,'end'); pop_tag()
|
||||
|
||||
free_tmp(itr) #REG
|
||||
free_tmp(i)
|
||||
|
||||
def do_comp(t,r=None):
|
||||
name = 'comp:'+get_tag()
|
||||
r = do_local(Token(t.pos,'name',name))
|
||||
code(LIST,r,0,0)
|
||||
key = Token(t.pos,'get',None,[
|
||||
Token(t.pos,'reg',r),
|
||||
Token(t.pos,'symbol','None')])
|
||||
ap = Token(t.pos,'symbol','=',[key,t.items[0]])
|
||||
do(Token(t.pos,'for',None,[t.items[1],t.items[2],ap]))
|
||||
return r
|
||||
|
||||
def do_if(t):
|
||||
items = t.items
|
||||
t = get_tag()
|
||||
n = 0
|
||||
for tt in items:
|
||||
tag(t,n)
|
||||
if tt.type == 'elif':
|
||||
a = do(tt.items[0]); code(IF,a); free_tmp(a);
|
||||
jump(t,n+1)
|
||||
free_tmp(do(tt.items[1])) #REG
|
||||
elif tt.type == 'else':
|
||||
free_tmp(do(tt.items[0])) #REG
|
||||
else:
|
||||
raise
|
||||
jump(t,'end')
|
||||
n += 1
|
||||
tag(t,n)
|
||||
tag(t,'end')
|
||||
|
||||
def do_try(t):
|
||||
items = t.items
|
||||
t = get_tag()
|
||||
setjmp(t,'except')
|
||||
free_tmp(do(items[0])) #REG
|
||||
jump(t,'end')
|
||||
tag(t,'except')
|
||||
free_tmp(do(items[1].items[1])) #REG
|
||||
tag(t,'end')
|
||||
|
||||
def do_return(t):
|
||||
if t.items: r = do(t.items[0])
|
||||
else: r = _do_none()
|
||||
code(RETURN,r)
|
||||
free_tmp(r)
|
||||
return
|
||||
def do_raise(t):
|
||||
if t.items: r = do(t.items[0])
|
||||
else: r = _do_none()
|
||||
code(RAISE,r)
|
||||
free_tmp(r)
|
||||
return
|
||||
|
||||
def do_statements(t):
|
||||
for tt in t.items: free_tmp(do(tt))
|
||||
|
||||
def do_list(t,r=None):
|
||||
r = get_tmp(r)
|
||||
manage_seq(LIST,r,t.items)
|
||||
return r
|
||||
|
||||
def do_dict(t,r=None):
|
||||
r = get_tmp(r)
|
||||
manage_seq(DICT,r,t.items)
|
||||
return r
|
||||
|
||||
def do_get(t,r=None):
|
||||
items = t.items
|
||||
return infix(GET,items[0],items[1],r)
|
||||
|
||||
def do_break(t): jump(D.tstack[-1],'break')
|
||||
def do_continue(t): jump(D.tstack[-1],'continue')
|
||||
def do_pass(t): code(PASS)
|
||||
|
||||
def do_info(name='?'):
|
||||
if '-nopos' in ARGV: return
|
||||
code(FILE,free_tmp(_do_string(D.fname)))
|
||||
code(NAME,free_tmp(_do_string(name)))
|
||||
def do_module(t):
|
||||
do_info()
|
||||
free_tmp(do(t.items[0])) #REG
|
||||
def do_reg(t,r=None): return t.val
|
||||
|
||||
fmap = {
|
||||
'module':do_module,'statements':do_statements,'def':do_def,
|
||||
'return':do_return,'while':do_while,'if':do_if,
|
||||
'break':do_break,'pass':do_pass,'continue':do_continue,'for':do_for,
|
||||
'class':do_class,'raise':do_raise,'try':do_try,'import':do_import,
|
||||
'globals':do_globals,'del':do_del,'from':do_from,
|
||||
}
|
||||
rmap = {
|
||||
'list':do_list, 'tuple':do_list, 'dict':do_dict, 'slice':do_list,
|
||||
'comp':do_comp, 'name':do_name,'symbol':do_symbol,'number':do_number,
|
||||
'string':do_string,'get':do_get, 'call':do_call, 'reg':do_reg,
|
||||
}
|
||||
|
||||
def do(t,r=None):
|
||||
if t.pos: setpos(t.pos)
|
||||
try:
|
||||
if t.type in rmap:
|
||||
return rmap[t.type](t,r)
|
||||
return fmap[t.type](t)
|
||||
except:
|
||||
if D.error: raise
|
||||
D.error = True
|
||||
tokenize.u_error('encode',D.code,t.pos)
|
||||
|
||||
def encode(fname,s,t):
|
||||
t = Token((1,1),'module','module',[t])
|
||||
global D
|
||||
s = tokenize.clean(s)
|
||||
D = DState(s,fname)
|
||||
D.begin(True)
|
||||
do(t)
|
||||
D.end()
|
||||
map_tags()
|
||||
out = D.out; D = None
|
||||
return ''.join(out)
|
||||
|
152
programs/develop/tinypy/tinypy/gc.c
Normal file
152
programs/develop/tinypy/tinypy/gc.c
Normal file
@ -0,0 +1,152 @@
|
||||
/* tp_obj tp_track(TP,tp_obj v) { return v; }
|
||||
void tp_grey(TP,tp_obj v) { }
|
||||
void tp_full(TP) { }
|
||||
void tp_gc_init(TP) { }
|
||||
void tp_gc_deinit(TP) { }
|
||||
void tp_delete(TP,tp_obj v) { }*/
|
||||
|
||||
void tp_grey(TP,tp_obj v) {
|
||||
if (v.type < TP_STRING || (!v.gci.data) || *v.gci.data) { return; }
|
||||
*v.gci.data = 1;
|
||||
if (v.type == TP_STRING || v.type == TP_DATA) {
|
||||
_tp_list_appendx(tp,tp->black,v);
|
||||
return;
|
||||
}
|
||||
_tp_list_appendx(tp,tp->grey,v);
|
||||
}
|
||||
|
||||
void tp_follow(TP,tp_obj v) {
|
||||
int type = v.type;
|
||||
if (type == TP_LIST) {
|
||||
int n;
|
||||
for (n=0; n<v.list.val->len; n++) {
|
||||
tp_grey(tp,v.list.val->items[n]);
|
||||
}
|
||||
}
|
||||
if (type == TP_DICT) {
|
||||
int i;
|
||||
for (i=0; i<v.dict.val->len; i++) {
|
||||
int n = _tp_dict_next(tp,v.dict.val);
|
||||
tp_grey(tp,v.dict.val->items[n].key);
|
||||
tp_grey(tp,v.dict.val->items[n].val);
|
||||
}
|
||||
}
|
||||
if (type == TP_FNC) {
|
||||
tp_grey(tp,v.fnc.info->self);
|
||||
tp_grey(tp,v.fnc.info->globals);
|
||||
}
|
||||
}
|
||||
|
||||
void tp_reset(TP) {
|
||||
int n;
|
||||
_tp_list *tmp;
|
||||
for (n=0; n<tp->black->len; n++) {
|
||||
*tp->black->items[n].gci.data = 0;
|
||||
}
|
||||
tmp = tp->white;
|
||||
tp->white = tp->black;
|
||||
tp->black = tmp;
|
||||
}
|
||||
|
||||
void tp_gc_init(TP) {
|
||||
tp->white = _tp_list_new();
|
||||
tp->strings = _tp_dict_new();
|
||||
tp->grey = _tp_list_new();
|
||||
tp->black = _tp_list_new();
|
||||
tp->steps = 0;
|
||||
}
|
||||
|
||||
void tp_gc_deinit(TP) {
|
||||
_tp_list_free(tp->white);
|
||||
_tp_dict_free(tp->strings);
|
||||
_tp_list_free(tp->grey);
|
||||
_tp_list_free(tp->black);
|
||||
}
|
||||
|
||||
void tp_delete(TP,tp_obj v) {
|
||||
int type = v.type;
|
||||
if (type == TP_LIST) {
|
||||
_tp_list_free(v.list.val);
|
||||
return;
|
||||
} else if (type == TP_DICT) {
|
||||
_tp_dict_free(v.dict.val);
|
||||
return;
|
||||
} else if (type == TP_STRING) {
|
||||
tp_free(v.string.info);
|
||||
return;
|
||||
} else if (type == TP_DATA) {
|
||||
if (v.data.info->free) {
|
||||
v.data.info->free(tp,v);
|
||||
}
|
||||
tp_free(v.data.info);
|
||||
return;
|
||||
} else if (type == TP_FNC) {
|
||||
tp_free(v.fnc.info);
|
||||
return;
|
||||
}
|
||||
tp_raise(,"tp_delete(%s)",TP_CSTR(v));
|
||||
}
|
||||
|
||||
void tp_collect(TP) {
|
||||
int n;
|
||||
for (n=0; n<tp->white->len; n++) {
|
||||
tp_obj r = tp->white->items[n];
|
||||
if (*r.gci.data) { continue; }
|
||||
if (r.type == TP_STRING) {
|
||||
/*this can't be moved into tp_delete, because tp_delete is
|
||||
also used by tp_track_s to delete redundant strings*/
|
||||
_tp_dict_del(tp,tp->strings,r,"tp_collect");
|
||||
}
|
||||
tp_delete(tp,r);
|
||||
}
|
||||
tp->white->len = 0;
|
||||
tp_reset(tp);
|
||||
}
|
||||
|
||||
void _tp_gcinc(TP) {
|
||||
tp_obj v;
|
||||
if (!tp->grey->len) {
|
||||
return;
|
||||
}
|
||||
v = _tp_list_pop(tp,tp->grey,tp->grey->len-1,"_tp_gcinc");
|
||||
tp_follow(tp,v);
|
||||
_tp_list_appendx(tp,tp->black,v);
|
||||
}
|
||||
|
||||
void tp_full(TP) {
|
||||
while (tp->grey->len) {
|
||||
_tp_gcinc(tp);
|
||||
}
|
||||
tp_collect(tp);
|
||||
tp_follow(tp,tp->root);
|
||||
}
|
||||
|
||||
void tp_gcinc(TP) {
|
||||
tp->steps += 1;
|
||||
if (tp->steps < TP_GCMAX || tp->grey->len > 0) {
|
||||
_tp_gcinc(tp); _tp_gcinc(tp);
|
||||
}
|
||||
if (tp->steps < TP_GCMAX || tp->grey->len > 0) { return; }
|
||||
tp->steps = 0;
|
||||
tp_full(tp);
|
||||
return;
|
||||
}
|
||||
|
||||
tp_obj tp_track(TP,tp_obj v) {
|
||||
if (v.type == TP_STRING) {
|
||||
int i = _tp_dict_find(tp,tp->strings,v);
|
||||
if (i != -1) {
|
||||
tp_delete(tp,v);
|
||||
v = tp->strings->items[i].key;
|
||||
tp_grey(tp,v);
|
||||
return v;
|
||||
}
|
||||
_tp_dict_setx(tp,tp->strings,v,tp_True);
|
||||
}
|
||||
tp_gcinc(tp);
|
||||
tp_grey(tp,v);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
65
programs/develop/tinypy/tinypy/koconsole.c
Normal file
65
programs/develop/tinypy/tinypy/koconsole.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include "kolibri.h"
|
||||
|
||||
#define __stdcall __attribute__((stdcall))
|
||||
#define _cdecl __attribute__((cdecl))
|
||||
#define _stdcall __attribute__((stdcall))
|
||||
|
||||
void (* _stdcall con_init)(unsigned w_w, unsigned w_h, unsigned s_w, unsigned s_h, const char* t);
|
||||
int (* _cdecl con_printf)(const char* format,...);
|
||||
void (* _stdcall con_exit)(char bCloseWindow);
|
||||
void (* __stdcall con_gets)(char* str, int n);
|
||||
|
||||
void CONSOLE_INIT(const char title[])
|
||||
{
|
||||
kol_struct_import *imp;
|
||||
|
||||
if (!(imp = kol_cofflib_load("/sys/lib/console.obj")) ||
|
||||
!(con_init = ( _stdcall void (*)(unsigned, unsigned, unsigned, unsigned, const char*))
|
||||
kol_cofflib_procload (imp, "con_init")) ||
|
||||
!(con_printf = ( _cdecl int (*)(const char*,...))
|
||||
kol_cofflib_procload (imp, "con_printf"))||
|
||||
!(con_gets = ( __stdcall void (*)(char*, int))
|
||||
kol_cofflib_procload (imp, "con_gets"))||
|
||||
!(con_exit = ( _stdcall void (*)(char))
|
||||
kol_cofflib_procload (imp, "con_exit")))
|
||||
{
|
||||
kol_exit();
|
||||
}
|
||||
con_init(-1, -1, -1, -1, title);
|
||||
}
|
||||
kol_struct_import* kol_cofflib_load(char *name)
|
||||
{
|
||||
kol_struct_import* result;
|
||||
asm ("int $0x40":"=a"(result):"a"(68), "b"(19), "c"(name));
|
||||
return result;
|
||||
}
|
||||
|
||||
void* kol_cofflib_procload (kol_struct_import *imp, char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0;;i++)
|
||||
{
|
||||
if ( NULL == ((imp+i) -> name))
|
||||
break;
|
||||
else
|
||||
if ( 0 == strcmp(name, (imp+i)->name) )
|
||||
return (imp+i)->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kol_board_puts(char *s)
|
||||
{
|
||||
unsigned i;
|
||||
i = 0;
|
||||
while (*(s+i))
|
||||
{
|
||||
asm ("int $0x40"::"a"(63), "b"(1), "c"(*(s+i)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void kol_exit()
|
||||
{
|
||||
asm ("int $0x40"::"a"(-1));
|
||||
}
|
92
programs/develop/tinypy/tinypy/kolibri.h
Normal file
92
programs/develop/tinypy/tinypy/kolibri.h
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned p00 __attribute__((packed));
|
||||
unsigned p04 __attribute__((packed));
|
||||
unsigned p08 __attribute__((packed));
|
||||
unsigned p12 __attribute__((packed));
|
||||
unsigned p16 __attribute__((packed));
|
||||
char p20 __attribute__((packed));
|
||||
char *p21 __attribute__((packed));
|
||||
} kol_struct70 __attribute__((packed));
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned p00 __attribute__((packed));
|
||||
char p04 __attribute__((packed));
|
||||
char p05[3] __attribute__((packed));
|
||||
unsigned p08 __attribute__((packed));
|
||||
unsigned p12 __attribute__((packed));
|
||||
unsigned p16 __attribute__((packed));
|
||||
unsigned p20 __attribute__((packed));
|
||||
unsigned p24 __attribute__((packed));
|
||||
unsigned p28 __attribute__((packed));
|
||||
unsigned p32[2] __attribute__((packed));
|
||||
unsigned p40 __attribute__((packed));
|
||||
} kol_struct_BDVK __attribute__((packed));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name __attribute__((packed));
|
||||
void *data __attribute__((packed));
|
||||
} kol_struct_import __attribute__((packed));
|
||||
|
||||
|
||||
void kol_exit();
|
||||
void kol_sleep(unsigned d);
|
||||
void kol_wnd_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c);
|
||||
void kol_wnd_move(unsigned x, unsigned y);
|
||||
void kol_wnd_caption(char *s);
|
||||
void kol_event_mask(unsigned e);
|
||||
unsigned kol_event_wait();
|
||||
unsigned kol_event_wait_time(unsigned time);
|
||||
unsigned kol_event_check();
|
||||
void kol_paint_start();
|
||||
void kol_paint_end();
|
||||
void kol_paint_pixel(unsigned x, unsigned y, unsigned c);
|
||||
void kol_paint_bar(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c);
|
||||
void kol_paint_line(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned c);
|
||||
void kol_paint_string(unsigned x, unsigned y, char *s, unsigned c);
|
||||
void kol_paint_image(unsigned x, unsigned y, unsigned w, unsigned h, char *d);
|
||||
void kol_paint_image_pal(unsigned x, unsigned y, unsigned w, unsigned h, char *d, unsigned *palette);
|
||||
unsigned kol_key_get();
|
||||
unsigned kol_key_control();
|
||||
void kol_key_lang_set(unsigned lang);
|
||||
unsigned kol_key_lang_get();
|
||||
void kol_key_mode_set(unsigned mode);
|
||||
unsigned kol_key_mode_get();
|
||||
void kol_btn_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned d, unsigned c);
|
||||
unsigned kol_btn_get();
|
||||
void kol_btn_type(unsigned t);
|
||||
unsigned kol_mouse_pos();
|
||||
unsigned kol_mouse_posw();
|
||||
unsigned kol_mouse_btn();
|
||||
void kol_board_putc(char c);
|
||||
void kol_board_puts(char *s);
|
||||
void kol_board_puti(int n);
|
||||
int kol_file_70(kol_struct70 *k);
|
||||
kol_struct_import* kol_cofflib_load(char *name);
|
||||
void* kol_cofflib_procload (kol_struct_import *imp, char *name);
|
||||
unsigned kol_cofflib_procnum (kol_struct_import *imp);
|
||||
void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n);
|
||||
unsigned kol_system_end(unsigned param);
|
||||
unsigned kol_system_cpufreq();
|
||||
unsigned kol_system_mem();
|
||||
unsigned kol_system_memfree();
|
||||
unsigned kol_system_time_get();
|
||||
unsigned kol_system_date_get();
|
||||
void kol_path_file2dir(char *dir, char *fname);
|
||||
void kol_path_full(char *full, char *fname);
|
||||
void kol_screen_wait_rr();
|
||||
void kol_screen_get_size(unsigned *w, unsigned *h);
|
||||
unsigned kol_skin_height();
|
||||
unsigned kol_thread_start(unsigned start, unsigned stack);
|
||||
unsigned kol_time_tick();
|
||||
unsigned kol_sound_speaker(char data[]);
|
||||
unsigned kol_process_info(unsigned slot, char buf1k[]);
|
||||
int kol_process_kill_pid(unsigned process);
|
||||
void kol_get_kernel_ver(char buff16b[]);
|
||||
int kol_kill_process(unsigned process);
|
133
programs/develop/tinypy/tinypy/list.c
Normal file
133
programs/develop/tinypy/tinypy/list.c
Normal file
@ -0,0 +1,133 @@
|
||||
void _tp_list_realloc(_tp_list *self,int len) {
|
||||
if (!len) { len=1; }
|
||||
self->items = (tp_obj*)tp_realloc(self->items,len*sizeof(tp_obj));
|
||||
self->alloc = len;
|
||||
}
|
||||
|
||||
void _tp_list_set(TP,_tp_list *self,int k, tp_obj v, const char *error) {
|
||||
if (k >= self->len) { tp_raise(,"%s: KeyError: %d\n",error,k); }
|
||||
self->items[k] = v;
|
||||
tp_grey(tp,v);
|
||||
}
|
||||
void _tp_list_free(_tp_list *self) {
|
||||
tp_free(self->items);
|
||||
tp_free(self);
|
||||
}
|
||||
|
||||
tp_obj _tp_list_get(TP,_tp_list *self,int k,const char *error) {
|
||||
if (k >= self->len) { tp_raise(tp_None,"%s: KeyError: %d\n",error,k); }
|
||||
return self->items[k];
|
||||
}
|
||||
void _tp_list_insertx(TP,_tp_list *self, int n, tp_obj v) {
|
||||
if (self->len >= self->alloc) {
|
||||
_tp_list_realloc(self,self->alloc*2);
|
||||
}
|
||||
if (n < self->len) { memmove(&self->items[n+1],&self->items[n],sizeof(tp_obj)*(self->len-n)); }
|
||||
self->items[n] = v;
|
||||
self->len += 1;
|
||||
}
|
||||
void _tp_list_appendx(TP,_tp_list *self, tp_obj v) {
|
||||
_tp_list_insertx(tp,self,self->len,v);
|
||||
}
|
||||
void _tp_list_insert(TP,_tp_list *self, int n, tp_obj v) {
|
||||
_tp_list_insertx(tp,self,n,v);
|
||||
tp_grey(tp,v);
|
||||
}
|
||||
void _tp_list_append(TP,_tp_list *self, tp_obj v) {
|
||||
_tp_list_insert(tp,self,self->len,v);
|
||||
}
|
||||
tp_obj _tp_list_pop(TP,_tp_list *self, int n, const char *error) {
|
||||
tp_obj r = _tp_list_get(tp,self,n,error);
|
||||
if (n != self->len-1) { memmove(&self->items[n],&self->items[n+1],sizeof(tp_obj)*(self->len-(n+1))); }
|
||||
self->len -= 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int _tp_list_find(TP,_tp_list *self, tp_obj v) {
|
||||
int n;
|
||||
for (n=0; n<self->len; n++) {
|
||||
if (tp_cmp(tp,v,self->items[n]) == 0) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
tp_obj tp_index(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
int i = _tp_list_find(tp,self.list.val,v);
|
||||
if (i < 0) { tp_raise(tp_None,"tp_index(%s,%s) - item not found",TP_CSTR(self),TP_CSTR(v)); }
|
||||
return tp_number(i);
|
||||
}
|
||||
|
||||
_tp_list *_tp_list_new(void) {
|
||||
return (_tp_list*)tp_malloc(sizeof(_tp_list));
|
||||
}
|
||||
|
||||
tp_obj _tp_list_copy(TP, tp_obj rr) {
|
||||
tp_obj val = {TP_LIST};
|
||||
_tp_list *o = rr.list.val;
|
||||
_tp_list *r = _tp_list_new();
|
||||
*r = *o; r->gci = 0;
|
||||
r->items = (tp_obj*)tp_malloc(sizeof(tp_obj)*o->alloc);
|
||||
memcpy(r->items,o->items,sizeof(tp_obj)*o->alloc);
|
||||
val.list.val = r;
|
||||
return tp_track(tp,val);
|
||||
}
|
||||
|
||||
tp_obj tp_append(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
_tp_list_append(tp,self.list.val,v);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
tp_obj tp_pop(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
return _tp_list_pop(tp,self.list.val,self.list.val->len-1,"pop");
|
||||
}
|
||||
|
||||
tp_obj tp_insert(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
int n = TP_NUM();
|
||||
tp_obj v = TP_OBJ();
|
||||
_tp_list_insert(tp,self.list.val,n,v);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
tp_obj tp_extend(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
int i;
|
||||
for (i=0; i<v.list.val->len; i++) {
|
||||
_tp_list_append(tp,self.list.val,v.list.val->items[i]);
|
||||
}
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
tp_obj tp_list(TP) {
|
||||
tp_obj r = {TP_LIST};
|
||||
r.list.val = _tp_list_new();
|
||||
return tp ? tp_track(tp,r) : r;
|
||||
}
|
||||
|
||||
tp_obj tp_list_n(TP,int n,tp_obj *argv) {
|
||||
int i;
|
||||
tp_obj r = tp_list(tp); _tp_list_realloc(r.list.val,n);
|
||||
for (i=0; i<n; i++) {
|
||||
_tp_list_append(tp,r.list.val,argv[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int _tp_sort_cmp(tp_obj *a,tp_obj *b) {
|
||||
return tp_cmp(0,*a,*b);
|
||||
}
|
||||
|
||||
tp_obj tp_sort(TP) {
|
||||
tp_obj self = TP_OBJ();
|
||||
qsort(self.list.val->items, self.list.val->len, sizeof(tp_obj), (int(*)(const void*,const void*))_tp_sort_cmp);
|
||||
return tp_None;
|
||||
}
|
||||
|
68
programs/develop/tinypy/tinypy/misc.c
Normal file
68
programs/develop/tinypy/tinypy/misc.c
Normal file
@ -0,0 +1,68 @@
|
||||
tp_obj *tp_ptr(tp_obj o) {
|
||||
tp_obj *ptr = (tp_obj*)tp_malloc(sizeof(tp_obj)); *ptr = o;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
tp_obj _tp_dcall(TP,tp_obj fnc(TP)) {
|
||||
return fnc(tp);
|
||||
}
|
||||
tp_obj _tp_tcall(TP,tp_obj fnc) {
|
||||
if (fnc.fnc.ftype&2) {
|
||||
_tp_list_insert(tp,tp->params.list.val,0,fnc.fnc.info->self);
|
||||
}
|
||||
return _tp_dcall(tp,(tp_obj (*)(tp_vm *))fnc.fnc.val);
|
||||
}
|
||||
|
||||
tp_obj tp_fnc_new(TP,int t, void *v, tp_obj s, tp_obj g) {
|
||||
tp_obj r = {TP_FNC};
|
||||
_tp_fnc *info = (_tp_fnc*)tp_malloc(sizeof(_tp_fnc));
|
||||
info->self = s;
|
||||
info->globals = g;
|
||||
r.fnc.ftype = t;
|
||||
r.fnc.info = info;
|
||||
r.fnc.val = v;
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
tp_obj tp_def(TP,void *v, tp_obj g) {
|
||||
return tp_fnc_new(tp,1,v,tp_None,g);
|
||||
}
|
||||
|
||||
tp_obj tp_fnc(TP,tp_obj v(TP)) {
|
||||
return tp_fnc_new(tp,0,v,tp_None,tp_None);
|
||||
}
|
||||
|
||||
tp_obj tp_method(TP,tp_obj self,tp_obj v(TP)) {
|
||||
return tp_fnc_new(tp,2,v,self,tp_None);
|
||||
}
|
||||
|
||||
tp_obj tp_data(TP,int magic,void *v) {
|
||||
tp_obj r = {TP_DATA};
|
||||
r.data.info = (_tp_data*)tp_malloc(sizeof(_tp_data));
|
||||
r.data.val = v;
|
||||
r.data.magic = magic;
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
tp_obj tp_params(TP) {
|
||||
tp_obj r;
|
||||
tp->params = tp->_params.list.val->items[tp->cur];
|
||||
r = tp->_params.list.val->items[tp->cur];
|
||||
r.list.val->len = 0;
|
||||
return r;
|
||||
}
|
||||
tp_obj tp_params_n(TP,int n, tp_obj argv[]) {
|
||||
tp_obj r = tp_params(tp);
|
||||
int i; for (i=0; i<n; i++) { _tp_list_append(tp,r.list.val,argv[i]); }
|
||||
return r;
|
||||
}
|
||||
tp_obj tp_params_v(TP,int n,...) {
|
||||
int i;
|
||||
tp_obj r = tp_params(tp);
|
||||
va_list a; va_start(a,n);
|
||||
for (i=0; i<n; i++) {
|
||||
_tp_list_append(tp,r.list.val,va_arg(a,tp_obj));
|
||||
}
|
||||
va_end(a);
|
||||
return r;
|
||||
}
|
24
programs/develop/tinypy/tinypy/mymain.c
Normal file
24
programs/develop/tinypy/tinypy/mymain.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "tp.c"
|
||||
|
||||
const char header[]="TinyPy for kolibriOS";
|
||||
const int argc = 2;
|
||||
|
||||
void main(void) {
|
||||
char *argv[2]={"tpmain", ""};
|
||||
|
||||
CONSOLE_INIT(header);
|
||||
con_printf("TinyPy console, version 1.1.\n");
|
||||
con_printf("Enter program file:");
|
||||
if (!(argv[1] = malloc(256)))
|
||||
con_printf("Memory error\n");
|
||||
con_gets(argv[1], 256);
|
||||
argv[1][strlen(argv[1]) - 1] = '\0';
|
||||
con_printf("Running file %s\n", argv[1]);
|
||||
tp_vm *tp = tp_init(argc, argv);
|
||||
|
||||
tp_call(tp,"py2bc","tinypy",tp_None);
|
||||
tp_deinit(tp);
|
||||
return;
|
||||
}
|
||||
|
||||
/**/
|
276
programs/develop/tinypy/tinypy/ops.c
Normal file
276
programs/develop/tinypy/tinypy/ops.c
Normal file
@ -0,0 +1,276 @@
|
||||
tp_obj tp_str(TP,tp_obj self) {
|
||||
int type = self.type;
|
||||
if (type == TP_STRING) {
|
||||
return self;
|
||||
}
|
||||
if (type == TP_NUMBER) {
|
||||
tp_num v = self.number.val;
|
||||
if ((fabs(v)-fabs((long)v)) < 0.000001) { return tp_printf(tp,"%ld",(long)v); }
|
||||
return tp_printf(tp,"%f",v);
|
||||
} else if(type == TP_DICT) {
|
||||
return tp_printf(tp,"<dict 0x%x>",self.dict.val);
|
||||
} else if(type == TP_LIST) {
|
||||
return tp_printf(tp,"<list 0x%x>",self.list.val);
|
||||
} else if (type == TP_NONE) {
|
||||
return tp_string("None");
|
||||
} else if (type == TP_DATA) {
|
||||
return tp_printf(tp,"<data 0x%x>",self.data.val);
|
||||
} else if (type == TP_FNC) {
|
||||
return tp_printf(tp,"<fnc 0x%x>",self.fnc.info);
|
||||
}
|
||||
return tp_string("<?>");
|
||||
}
|
||||
|
||||
int tp_bool(TP,tp_obj v) {
|
||||
switch(v.type) {
|
||||
case TP_NUMBER: return v.number.val != 0;
|
||||
case TP_NONE: return 0;
|
||||
case TP_STRING: return v.string.len != 0;
|
||||
case TP_LIST: return v.list.val->len != 0;
|
||||
case TP_DICT: return v.dict.val->len != 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_has(TP,tp_obj self, tp_obj k) {
|
||||
int type = self.type;
|
||||
if (type == TP_DICT) {
|
||||
if (_tp_dict_find(tp,self.dict.val,k) != -1) { return tp_True; }
|
||||
return tp_False;
|
||||
} else if (type == TP_STRING && k.type == TP_STRING) {
|
||||
char *p = strstr(TP_CSTR(self),TP_CSTR(k));
|
||||
return tp_number(p != 0);
|
||||
} else if (type == TP_LIST) {
|
||||
return tp_number(_tp_list_find(tp,self.list.val,k)!=-1);
|
||||
}
|
||||
tp_raise(tp_None,"tp_has(%s,%s)",TP_CSTR(self),TP_CSTR(k));
|
||||
}
|
||||
|
||||
void tp_del(TP,tp_obj self, tp_obj k) {
|
||||
int type = self.type;
|
||||
if (type == TP_DICT) {
|
||||
_tp_dict_del(tp,self.dict.val,k,"tp_del");
|
||||
return;
|
||||
}
|
||||
tp_raise(,"tp_del(%s,%s)",TP_CSTR(self),TP_CSTR(k));
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_iter(TP,tp_obj self, tp_obj k) {
|
||||
int type = self.type;
|
||||
if (type == TP_LIST || type == TP_STRING) { return tp_get(tp,self,k); }
|
||||
if (type == TP_DICT && k.type == TP_NUMBER) {
|
||||
return self.dict.val->items[_tp_dict_next(tp,self.dict.val)].key;
|
||||
}
|
||||
tp_raise(tp_None,"tp_iter(%s,%s)",TP_CSTR(self),TP_CSTR(k));
|
||||
}
|
||||
|
||||
tp_obj tp_get(TP,tp_obj self, tp_obj k) {
|
||||
int type = self.type;
|
||||
tp_obj r;
|
||||
/*con_printf("tp_get %s %s\n", TP_CSTR(self), TP_CSTR(k));*/
|
||||
if (type == TP_DICT) {
|
||||
return _tp_dict_get(tp,self.dict.val,k,"tp_get");
|
||||
} else if (type == TP_LIST) {
|
||||
if (k.type == TP_NUMBER) {
|
||||
int l = tp_len(tp,self).number.val;
|
||||
int n = k.number.val;
|
||||
n = (n<0?l+n:n);
|
||||
return _tp_list_get(tp,self.list.val,n,"tp_get");
|
||||
} else if (k.type == TP_STRING) {
|
||||
if (strcmp("append",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_append);
|
||||
} else if (strcmp("pop",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_pop);
|
||||
} else if (strcmp("index",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_index);
|
||||
} else if (strcmp("sort",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_sort);
|
||||
} else if (strcmp("extend",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_extend);
|
||||
} else if (strcmp("*",TP_CSTR(k)) == 0) {
|
||||
tp_params_v(tp,1,self);
|
||||
r = tp_copy(tp);
|
||||
self.list.val->len=0;
|
||||
return r;
|
||||
}
|
||||
} else if (k.type == TP_NONE) {
|
||||
return _tp_list_pop(tp,self.list.val,0,"tp_get");
|
||||
}
|
||||
} else if (type == TP_STRING) {
|
||||
if (k.type == TP_NUMBER) {
|
||||
int l = self.string.len;
|
||||
int n = k.number.val;
|
||||
n = (n<0?l+n:n);
|
||||
if (n >= 0 && n < l) { return tp_string_n(tp->chars[(unsigned char)self.string.val[n]],1); }
|
||||
} else if (k.type == TP_STRING) {
|
||||
if (strcmp("join",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_join);
|
||||
} else if (strcmp("split",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_split);
|
||||
} else if (strcmp("index",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_str_index);
|
||||
} else if (strcmp("strip",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_strip);
|
||||
} else if (strcmp("replace",TP_CSTR(k)) == 0) {
|
||||
return tp_method(tp,self,tp_replace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k.type == TP_LIST) {
|
||||
int a,b,l;
|
||||
tp_obj tmp;
|
||||
l = tp_len(tp,self).number.val;
|
||||
tmp = tp_get(tp,k,tp_number(0));
|
||||
if (tmp.type == TP_NUMBER) { a = tmp.number.val; }
|
||||
else if(tmp.type == TP_NONE) { a = 0; }
|
||||
else { tp_raise(tp_None,"%s is not a number",TP_CSTR(tmp)); }
|
||||
tmp = tp_get(tp,k,tp_number(1));
|
||||
if (tmp.type == TP_NUMBER) { b = tmp.number.val; }
|
||||
else if(tmp.type == TP_NONE) { b = l; }
|
||||
else { tp_raise(tp_None,"%s is not a number",TP_CSTR(tmp)); }
|
||||
a = _tp_max(0,(a<0?l+a:a)); b = _tp_min(l,(b<0?l+b:b));
|
||||
if (type == TP_LIST) {
|
||||
return tp_list_n(tp,b-a,&self.list.val->items[a]);
|
||||
} else if (type == TP_STRING) {
|
||||
tp_obj r = tp_string_t(tp,b-a);
|
||||
char *ptr = r.string.info->s;
|
||||
memcpy(ptr,self.string.val+a,b-a); ptr[b-a]=0;
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con_printf("Raising exception\n");
|
||||
tp_raise(tp_None,"tp_get(%s,%s)",TP_CSTR(self),TP_CSTR(k));
|
||||
}
|
||||
|
||||
int tp_iget(TP,tp_obj *r, tp_obj self, tp_obj k) {
|
||||
if (self.type == TP_DICT) {
|
||||
int n = _tp_dict_find(tp,self.dict.val,k);
|
||||
if (n == -1) { return 0; }
|
||||
*r = self.dict.val->items[n].val;
|
||||
tp_grey(tp,*r);
|
||||
return 1;
|
||||
}
|
||||
if (self.type == TP_LIST && !self.list.val->len) { return 0; }
|
||||
*r = tp_get(tp,self,k); tp_grey(tp,*r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tp_set(TP,tp_obj self, tp_obj k, tp_obj v) {
|
||||
int type;
|
||||
con_printf("vm is %x self is %x k is %x v is %x", tp, self, k, v);
|
||||
type = self.type;
|
||||
if (type == TP_DICT) {
|
||||
_tp_dict_set(tp,self.dict.val,k,v);
|
||||
return;
|
||||
} else if (type == TP_LIST) {
|
||||
if (k.type == TP_NUMBER) {
|
||||
_tp_list_set(tp,self.list.val,k.number.val,v,"tp_set");
|
||||
return;
|
||||
} else if (k.type == TP_NONE) {
|
||||
_tp_list_append(tp,self.list.val,v);
|
||||
return;
|
||||
} else if (k.type == TP_STRING) {
|
||||
if (strcmp("*",TP_CSTR(k)) == 0) {
|
||||
tp_params_v(tp,2,self,v); tp_extend(tp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
tp_raise(,"tp_set(%s,%s,%s)",TP_CSTR(self),TP_CSTR(k),TP_CSTR(v));
|
||||
}
|
||||
|
||||
tp_obj tp_add(TP,tp_obj a, tp_obj b) {
|
||||
if (a.type == TP_NUMBER && a.type == b.type) {
|
||||
return tp_number(a.number.val+b.number.val);
|
||||
} else if (a.type == TP_STRING && a.type == b.type) {
|
||||
int al = a.string.len, bl = b.string.len;
|
||||
tp_obj r = tp_string_t(tp,al+bl);
|
||||
char *s = r.string.info->s;
|
||||
memcpy(s,a.string.val,al); memcpy(s+al,b.string.val,bl);
|
||||
return tp_track(tp,r);
|
||||
} else if (a.type == TP_LIST && a.type == b.type) {
|
||||
tp_obj r;
|
||||
tp_params_v(tp,1,a);
|
||||
r = tp_copy(tp);
|
||||
tp_params_v(tp,2,r,b);
|
||||
tp_extend(tp);
|
||||
return r;
|
||||
}
|
||||
tp_raise(tp_None,"tp_add(%s,%s)",TP_CSTR(a),TP_CSTR(b));
|
||||
}
|
||||
|
||||
tp_obj tp_mul(TP,tp_obj a, tp_obj b) {
|
||||
if (a.type == TP_NUMBER && a.type == b.type) {
|
||||
return tp_number(a.number.val*b.number.val);
|
||||
} else if (a.type == TP_STRING && b.type == TP_NUMBER) {
|
||||
int al = a.string.len; int n = b.number.val;
|
||||
tp_obj r = tp_string_t(tp,al*n);
|
||||
char *s = r.string.info->s;
|
||||
int i; for (i=0; i<n; i++) { memcpy(s+al*i,a.string.val,al); }
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
tp_raise(tp_None,"tp_mul(%s,%s)",TP_CSTR(a),TP_CSTR(b));
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_len(TP,tp_obj self) {
|
||||
int type = self.type;
|
||||
if (type == TP_STRING) {
|
||||
return tp_number(self.string.len);
|
||||
} else if (type == TP_DICT) {
|
||||
return tp_number(self.dict.val->len);
|
||||
} else if (type == TP_LIST) {
|
||||
return tp_number(self.list.val->len);
|
||||
}
|
||||
tp_raise(tp_None,"tp_len(%s)",TP_CSTR(self));
|
||||
}
|
||||
|
||||
int tp_cmp(TP,tp_obj a, tp_obj b) {
|
||||
if (a.type != b.type) { return a.type-b.type; }
|
||||
switch(a.type) {
|
||||
case TP_NONE: return 0;
|
||||
case TP_NUMBER: return _tp_sign(a.number.val-b.number.val);
|
||||
case TP_STRING: {
|
||||
int v = memcmp(a.string.val,b.string.val,_tp_min(a.string.len,b.string.len));
|
||||
if (v == 0) { v = a.string.len-b.string.len; }
|
||||
return v;
|
||||
}
|
||||
case TP_LIST: {
|
||||
int n,v; for(n=0;n<_tp_min(a.list.val->len,b.list.val->len);n++) {
|
||||
tp_obj aa = a.list.val->items[n]; tp_obj bb = b.list.val->items[n];
|
||||
if (aa.type == TP_LIST && bb.type == TP_LIST) { v = aa.list.val-bb.list.val; } else { v = tp_cmp(tp,aa,bb); }
|
||||
if (v) { return v; } }
|
||||
return a.list.val->len-b.list.val->len;
|
||||
}
|
||||
case TP_DICT: return a.dict.val - b.dict.val;
|
||||
case TP_FNC: return a.fnc.info - b.fnc.info;
|
||||
case TP_DATA: return (char*)a.data.val - (char*)b.data.val;
|
||||
}
|
||||
tp_raise(0,"tp_cmp(%s,%s)",TP_CSTR(a),TP_CSTR(b));
|
||||
}
|
||||
|
||||
#define TP_OP(name,expr) \
|
||||
tp_obj name(TP,tp_obj _a,tp_obj _b) { \
|
||||
if (_a.type == TP_NUMBER && _a.type == _b.type) { \
|
||||
tp_num a = _a.number.val; tp_num b = _b.number.val; \
|
||||
return tp_number(expr); \
|
||||
} \
|
||||
tp_raise(tp_None,"%s(%s,%s)",#name,TP_CSTR(_a),TP_CSTR(_b)); \
|
||||
}
|
||||
|
||||
TP_OP(tp_and,((long)a)&((long)b));
|
||||
TP_OP(tp_or,((long)a)|((long)b));
|
||||
TP_OP(tp_mod,((long)a)%((long)b));
|
||||
TP_OP(tp_lsh,((long)a)<<((long)b));
|
||||
TP_OP(tp_rsh,((long)a)>>((long)b));
|
||||
TP_OP(tp_sub,a-b);
|
||||
TP_OP(tp_div,a/b);
|
||||
TP_OP(tp_pow,pow(a,b));
|
||||
|
||||
|
||||
/**/
|
408
programs/develop/tinypy/tinypy/parse.py
Normal file
408
programs/develop/tinypy/tinypy/parse.py
Normal file
@ -0,0 +1,408 @@
|
||||
import tokenize
|
||||
from tokenize import Token
|
||||
if '.' in str(1.0):
|
||||
from boot import *
|
||||
|
||||
def check(t,*vs):
|
||||
if vs[0] == None: return True
|
||||
if t.type in vs: return True
|
||||
if t.type == 'symbol' and t.val in vs: return True
|
||||
return False
|
||||
|
||||
def tweak(k,v):
|
||||
P.stack.append((k,dmap[k]))
|
||||
if v: dmap[k] = omap[k]
|
||||
else: dmap[k] = {'lbp':0,'nud':itself}
|
||||
def restore():
|
||||
k,v = P.stack.pop()
|
||||
dmap[k] = v
|
||||
|
||||
def cpy(d):
|
||||
r = {}
|
||||
for k in d: r[k] = d[k]
|
||||
return r
|
||||
|
||||
class PData:
|
||||
def __init__(self,s,tokens):
|
||||
self.s = s
|
||||
self.tokens = tokens
|
||||
self.pos = 0
|
||||
self.token = None
|
||||
self.stack = []
|
||||
def init(self):
|
||||
global omap,dmap
|
||||
omap = cpy(base_dmap)
|
||||
dmap = cpy(base_dmap)
|
||||
self.advance()
|
||||
def advance(self,val=None):
|
||||
if not check(self.token,val):
|
||||
error('expected '+val,self.token)
|
||||
if self.pos < len(self.tokens):
|
||||
t = self.tokens[self.pos]
|
||||
self.pos += 1
|
||||
else:
|
||||
t = Token((0,0),'eof','eof')
|
||||
self.token = do(t)
|
||||
return t
|
||||
def error(ctx,t):
|
||||
print t
|
||||
tokenize.u_error(ctx,P.s,t.pos)
|
||||
|
||||
def nud(t):
|
||||
#if 'nud' not in t:
|
||||
# error('no nud',t)
|
||||
return t.nud(t)
|
||||
def led(t,left):
|
||||
#if 'led' not in t:
|
||||
# error('no led',t)
|
||||
return t.led(t,left)
|
||||
def get_lbp(t):
|
||||
#if 'lbp' not in t:
|
||||
# error('no lbp',t)
|
||||
return t.lbp
|
||||
def get_items(t):
|
||||
#if 'items' not in t:
|
||||
# error('no items',t)
|
||||
return t.items
|
||||
|
||||
def expression(rbp):
|
||||
t = P.token
|
||||
advance()
|
||||
left = nud(t)
|
||||
while rbp < get_lbp(P.token):
|
||||
t = P.token
|
||||
advance()
|
||||
left = led(t,left)
|
||||
return left
|
||||
|
||||
def infix_led(t,left):
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_is(t,left):
|
||||
if check(P.token,'not'):
|
||||
t.val = 'isnot'
|
||||
advance('not')
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_not(t,left):
|
||||
advance('in')
|
||||
t.val = 'notin'
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_tuple(t,left):
|
||||
r = expression(t.bp)
|
||||
if left.val == ',':
|
||||
left.items.append(r)
|
||||
return left
|
||||
t.items = [left,r]
|
||||
t.type = 'tuple'
|
||||
return t
|
||||
def lst(t):
|
||||
if t == None: return []
|
||||
if check(t,',','tuple','statements'):
|
||||
return get_items(t)
|
||||
return [t]
|
||||
def ilst(typ,t):
|
||||
return Token(t.pos,typ,typ,lst(t))
|
||||
|
||||
def call_led(t,left):
|
||||
r = Token(t.pos,'call','$',[left])
|
||||
while not check(P.token,')'):
|
||||
tweak(',',0)
|
||||
r.items.append(expression(0))
|
||||
if P.token.val == ',': advance(',')
|
||||
restore()
|
||||
advance(")")
|
||||
return r
|
||||
def get_led(t,left):
|
||||
r = Token(t.pos,'get','.',[left])
|
||||
items = [left]
|
||||
more = False
|
||||
while not check(P.token,']'):
|
||||
more = False
|
||||
if check(P.token,':'):
|
||||
items.append(Token(P.token.pos,'symbol','None'))
|
||||
else:
|
||||
items.append(expression(0))
|
||||
if check(P.token,':'):
|
||||
advance(':')
|
||||
more = True
|
||||
if more:
|
||||
items.append(Token(P.token.pos,'symbol','None'))
|
||||
if len(items) > 2:
|
||||
items = [left,Token(t.pos,'slice',':',items[1:])]
|
||||
r.items = items
|
||||
advance("]")
|
||||
return r
|
||||
def dot_led(t,left):
|
||||
r = expression(t.bp)
|
||||
r.type = 'string'
|
||||
t.items = [left,r]
|
||||
return t
|
||||
|
||||
def itself(t):
|
||||
return t
|
||||
def paren_nud(t):
|
||||
tweak(',',1)
|
||||
r = expression(0)
|
||||
restore()
|
||||
advance(')')
|
||||
return r
|
||||
def list_nud(t):
|
||||
t.type = 'list'
|
||||
t.val = '[]'
|
||||
t.items = []
|
||||
next = P.token
|
||||
tweak(',',0)
|
||||
while not check(P.token,'for',']'):
|
||||
r = expression(0)
|
||||
t.items.append(r)
|
||||
if P.token.val == ',': advance(',')
|
||||
if check(P.token,'for'):
|
||||
t.type = 'comp'
|
||||
advance('for')
|
||||
tweak('in',0)
|
||||
t.items.append(expression(0))
|
||||
advance('in')
|
||||
t.items.append(expression(0))
|
||||
restore()
|
||||
restore()
|
||||
advance(']')
|
||||
return t
|
||||
def dict_nud(t):
|
||||
t.type='dict'
|
||||
t.val = '{}'
|
||||
t.items = []
|
||||
tweak(',',0)
|
||||
while not check(P.token,'}'):
|
||||
t.items.append(expression(0))
|
||||
if check(P.token,':',','): advance()
|
||||
restore()
|
||||
advance('}')
|
||||
return t
|
||||
|
||||
def advance(t=None):
|
||||
return P.advance(t)
|
||||
|
||||
def block():
|
||||
items = []
|
||||
tok = P.token
|
||||
|
||||
while check(P.token,'nl'): advance()
|
||||
if check(P.token,'indent'):
|
||||
advance('indent')
|
||||
while not check(P.token,'dedent'):
|
||||
items.append(expression(0))
|
||||
while check(P.token,';','nl'): advance()
|
||||
advance('dedent')
|
||||
else:
|
||||
items.append(expression(0))
|
||||
while check(P.token,';'):
|
||||
advance(';')
|
||||
items.append(expression(0))
|
||||
while check(P.token,'nl'): advance()
|
||||
|
||||
if len(items) > 1:
|
||||
return Token(tok.pos,'statements',';',items)
|
||||
return items.pop()
|
||||
|
||||
def def_nud(t):
|
||||
items = t.items = []
|
||||
items.append(P.token); advance()
|
||||
advance('(')
|
||||
r = Token(t.pos,'symbol','():',[])
|
||||
items.append(r)
|
||||
while not check(P.token,')'):
|
||||
tweak(',',0)
|
||||
r.items.append(expression(0))
|
||||
if check(P.token,','): advance(',')
|
||||
restore()
|
||||
advance(')')
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
|
||||
|
||||
def while_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
def class_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance(':')
|
||||
items.append(ilst('methods',block()))
|
||||
return t
|
||||
|
||||
def from_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance('import')
|
||||
items.append(expression(0))
|
||||
return t
|
||||
|
||||
def for_nud(t):
|
||||
items = t.items = []
|
||||
tweak('in',0)
|
||||
items.append(expression(0))
|
||||
advance('in')
|
||||
items.append(expression(0))
|
||||
restore()
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
def if_nud(t):
|
||||
items = t.items = []
|
||||
a = expression(0)
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(t.pos,'elif','elif',[a,b]))
|
||||
while check(P.token,'elif'):
|
||||
tok = P.token
|
||||
advance('elif')
|
||||
a = expression(0)
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'elif','elif',[a,b]))
|
||||
if check(P.token,'else'):
|
||||
tok = P.token
|
||||
advance('else')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'else','else',[b]))
|
||||
return t
|
||||
def try_nud(t):
|
||||
items = t.items = []
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(b)
|
||||
while check(P.token,'except'):
|
||||
tok = P.token
|
||||
advance('except')
|
||||
if not check(P.token,':'): a = expression(0)
|
||||
else: a = Token(tok.pos,'symbol','None')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'except','except',[a,b]))
|
||||
if check(P.token,'else'):
|
||||
tok = P.token
|
||||
advance('else')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'else','else',[b]))
|
||||
return t
|
||||
def prefix_nud(t):
|
||||
#bp = 70
|
||||
#if 'bp' in t: bp = t['bp']
|
||||
bp = t.bp
|
||||
t.items = [expression(bp)]
|
||||
return t
|
||||
def prefix_nud0(t):
|
||||
if check(P.token,'nl',';','eof','dedent'): return t
|
||||
return prefix_nud(t)
|
||||
def prefix_nuds(t):
|
||||
r = expression(0)
|
||||
return ilst(t.type,r)
|
||||
|
||||
def prefix_neg(t):
|
||||
r = expression(50)
|
||||
if r.type == 'number':
|
||||
r.val = str(-float(r.val))
|
||||
return r
|
||||
t.items = [Token(t.pos,'number','0'),r]
|
||||
return t
|
||||
def vargs_nud(t):
|
||||
r = prefix_nud(t)
|
||||
t.type = 'args'
|
||||
t.val = '*'
|
||||
return t
|
||||
def nargs_nud(t):
|
||||
r = prefix_nud(t)
|
||||
t.type = 'nargs'
|
||||
t.val = '**'
|
||||
return t
|
||||
|
||||
|
||||
base_dmap = {
|
||||
',':{'lbp':20,'bp':20,'led':infix_tuple},
|
||||
'+':{'lbp':50,'bp':50,'led':infix_led},
|
||||
'-':{'lbp':50,'nud':prefix_neg,
|
||||
'bp':50,'led':infix_led},
|
||||
'not':{'lbp':35,'nud':prefix_nud,'bp':35,
|
||||
'bp':35,'led':infix_not },
|
||||
'%':{'lbp':60,'bp':60,'led':infix_led},
|
||||
'*':{'lbp':60,'nud':vargs_nud,
|
||||
'bp':60,'led':infix_led,},
|
||||
'**': {'lbp':65,'nud':nargs_nud,
|
||||
'bp':65,'led':infix_led,},
|
||||
'/':{'lbp':60,'bp':60,'led':infix_led},
|
||||
'(':{'lbp':70,'nud':paren_nud,
|
||||
'bp':80,'led':call_led,},
|
||||
'[':{'lbp':70,'nud':list_nud,
|
||||
'bp':80,'led':get_led,},
|
||||
'{':{'lbp':0,'nud':dict_nud,},
|
||||
'.':{'lbp':80,'bp':80,'led':dot_led,'type':'get',},
|
||||
'break':{'lbp':0,'nud':itself,'type':'break'},
|
||||
'pass':{'lbp':0,'nud':itself,'type':'pass'},
|
||||
'continue':{'lbp':0,'nud':itself,'type':'continue'},
|
||||
'eof':{'lbp':0,'type':'eof','val':'eof'},
|
||||
'def':{'lbp':0,'nud':def_nud,'type':'def',},
|
||||
'while':{'lbp':0,'nud':while_nud,'type':'while',},
|
||||
'for':{'lbp':0,'nud':for_nud,'type':'for',},
|
||||
'try':{'lbp':0,'nud':try_nud,'type':'try',},
|
||||
'if':{'lbp':0,'nud':if_nud,'type':'if',},
|
||||
'class':{'lbp':0,'nud':class_nud,'type':'class',},
|
||||
'raise':{'lbp':0,'nud':prefix_nud0,'type':'raise','bp':20,},
|
||||
'return':{'lbp':0,'nud':prefix_nud0,'type':'return','bp':10,},
|
||||
'import':{'lbp':0,'nud':prefix_nuds,'type':'import','bp':20,},
|
||||
'from':{'lbp':0,'nud':from_nud,'type':'from','bp':20,},
|
||||
'del':{'lbp':0,'nud':prefix_nuds,'type':'del','bp':10,},
|
||||
'global':{'lbp':0,'nud':prefix_nuds,'type':'globals','bp':20,},
|
||||
|
||||
'=':{
|
||||
'lbp':10,'bp':9,'led':infix_led,
|
||||
},
|
||||
}
|
||||
|
||||
def i_infix(bp,led,*vs):
|
||||
for v in vs: base_dmap[v] = {'lbp':bp,'bp':bp,'led':led}
|
||||
i_infix(40,infix_led,'<','>','<=','>=','!=','==')
|
||||
i_infix(40,infix_is,'is','in')
|
||||
i_infix(10,infix_led,'+=','-=','*=','/=')
|
||||
i_infix(31,infix_led,'and','&')
|
||||
i_infix(30,infix_led,'or','|')
|
||||
i_infix(36,infix_led,'<<','>>')
|
||||
def i_terms(*vs):
|
||||
for v in vs: base_dmap[v] = {'lbp':0,'nud':itself}
|
||||
i_terms(')','}',']',';',':','nl','elif','else','True','False','None','name','string','number','indent','dedent','except')
|
||||
base_dmap['nl']['val'] = 'nl'
|
||||
|
||||
def gmap(t,v):
|
||||
if v not in dmap:
|
||||
error('unknown "%s"'%v,t)
|
||||
return dmap[v]
|
||||
|
||||
def do(t):
|
||||
if t.type == 'symbol': r = gmap(t,t.val)
|
||||
else: r = gmap(t,t.type)
|
||||
merge(t,r)
|
||||
return t
|
||||
def do_module():
|
||||
tok = P.token
|
||||
items = []
|
||||
while not check(P.token,'eof'):
|
||||
items.append(block())
|
||||
if len(items) > 1:
|
||||
return Token(tok.pos,'statements',';',items)
|
||||
return items.pop()
|
||||
|
||||
def parse(s,tokens,wrap=0):
|
||||
global P
|
||||
s = tokenize.clean(s)
|
||||
P=PData(s,tokens); P.init()
|
||||
r = do_module()
|
||||
P = None
|
||||
return r
|
||||
|
56
programs/develop/tinypy/tinypy/py2bc.py
Normal file
56
programs/develop/tinypy/tinypy/py2bc.py
Normal file
@ -0,0 +1,56 @@
|
||||
print("Starting py2bc")
|
||||
if not (str(1.0) == "1"):
|
||||
from boot import *
|
||||
|
||||
import tokenize,parse,encode
|
||||
|
||||
def _compile(s,fname):
|
||||
tokens = tokenize.tokenize(s)
|
||||
t = parse.parse(s,tokens)
|
||||
r = encode.encode(fname,s,t)
|
||||
return r
|
||||
|
||||
def _import(name):
|
||||
if name in MODULES:
|
||||
return MODULES[name]
|
||||
py = name+".py"
|
||||
tpc = name+".tpc"
|
||||
print("CP")
|
||||
if exists(py):
|
||||
if not exists(tpc) or mtime(py) > mtime(tpc):
|
||||
s = load(py)
|
||||
code = _compile(s,py)
|
||||
save(tpc,code)
|
||||
if not exists(tpc): raise
|
||||
code = load(tpc)
|
||||
g = {'__name__':name,'__code__':code}
|
||||
g['__dict__'] = g
|
||||
MODULES[name] = g
|
||||
exec(code,g)
|
||||
return g
|
||||
def _init():
|
||||
BUILTINS['compile'] = _compile
|
||||
BUILTINS['import'] = _import
|
||||
|
||||
def import_fname(fname,name):
|
||||
g = {}
|
||||
g['__name__'] = name
|
||||
MODULES[name] = g
|
||||
s = load(fname)
|
||||
code = _compile(s,fname)
|
||||
g['__code__'] = code
|
||||
exec(code,g)
|
||||
return g
|
||||
|
||||
def tinypy():
|
||||
print("tinypy called")
|
||||
return import_fname(ARGV[0],'__main__')
|
||||
|
||||
def main(src,dest):
|
||||
s = load(src)
|
||||
r = _compile(s,src)
|
||||
save(dest,r)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running main")
|
||||
main(ARGV[1],ARGV[2])
|
165
programs/develop/tinypy/tinypy/string.c
Normal file
165
programs/develop/tinypy/tinypy/string.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
tp_obj tp_string_t(TP, int n) {
|
||||
tp_obj r = tp_string_n(0,n);
|
||||
r.string.info = (_tp_string*)tp_malloc(sizeof(_tp_string)+n);
|
||||
r.string.val = r.string.info->s;
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj tp_printf(TP, char const *fmt,...) {
|
||||
int l;
|
||||
tp_obj r;
|
||||
char tmp[2000];
|
||||
char *s;
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
l = vsnprintf(tmp, sizeof(tmp), fmt,arg);
|
||||
r = tp_string_t(tp,l);
|
||||
s = r.string.info->s;
|
||||
va_end(arg);
|
||||
va_start(arg, fmt);
|
||||
vsprintf(s,fmt,arg);
|
||||
va_end(arg);
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
int _tp_str_index(tp_obj s, tp_obj k) {
|
||||
int i=0;
|
||||
while ((s.string.len - i) >= k.string.len) {
|
||||
if (memcmp(s.string.val+i,k.string.val,k.string.len) == 0) {
|
||||
return i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
tp_obj tp_join(TP) {
|
||||
tp_obj delim = TP_OBJ();
|
||||
tp_obj val = TP_OBJ();
|
||||
int l=0,i;
|
||||
tp_obj r;
|
||||
char *s;
|
||||
for (i=0; i<val.list.val->len; i++) {
|
||||
if (i!=0) { l += delim.string.len; }
|
||||
l += tp_str(tp,val.list.val->items[i]).string.len;
|
||||
}
|
||||
r = tp_string_t(tp,l);
|
||||
s = r.string.info->s;
|
||||
l = 0;
|
||||
for (i=0; i<val.list.val->len; i++) {
|
||||
tp_obj e;
|
||||
if (i!=0) {
|
||||
memcpy(s+l,delim.string.val,delim.string.len); l += delim.string.len;
|
||||
}
|
||||
e = tp_str(tp,val.list.val->items[i]);
|
||||
memcpy(s+l,e.string.val,e.string.len); l += e.string.len;
|
||||
}
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
tp_obj tp_string_slice(TP,tp_obj s, int a, int b) {
|
||||
tp_obj r = tp_string_t(tp,b-a);
|
||||
char *m = r.string.info->s;
|
||||
memcpy(m,s.string.val+a,b-a);
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
tp_obj tp_split(TP) {
|
||||
tp_obj v = TP_OBJ();
|
||||
tp_obj d = TP_OBJ();
|
||||
tp_obj r = tp_list(tp);
|
||||
|
||||
int i;
|
||||
while ((i=_tp_str_index(v,d))!=-1) {
|
||||
_tp_list_append(tp,r.list.val,tp_string_slice(tp,v,0,i));
|
||||
v.string.val += i + d.string.len; v.string.len -= i + d.string.len;
|
||||
/* tp_grey(tp,r); // should stop gc or something instead*/
|
||||
}
|
||||
_tp_list_append(tp,r.list.val,tp_string_slice(tp,v,0,v.string.len));
|
||||
/* tp_grey(tp,r); // should stop gc or something instead*/
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_find(TP) {
|
||||
tp_obj s = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
return tp_number(_tp_str_index(s,v));
|
||||
}
|
||||
|
||||
tp_obj tp_str_index(TP) {
|
||||
tp_obj s = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
int n = _tp_str_index(s,v);
|
||||
if (n >= 0) { return tp_number(n); }
|
||||
tp_raise(tp_None,"tp_str_index(%s,%s)",s,v);
|
||||
}
|
||||
|
||||
tp_obj tp_str2(TP) {
|
||||
tp_obj v = TP_OBJ();
|
||||
return tp_str(tp,v);
|
||||
}
|
||||
|
||||
tp_obj tp_chr(TP) {
|
||||
int v = TP_NUM();
|
||||
return tp_string_n(tp->chars[(unsigned char)v],1);
|
||||
}
|
||||
tp_obj tp_ord(TP) {
|
||||
char const *s = TP_STR();
|
||||
return tp_number((unsigned char)s[0]);
|
||||
}
|
||||
|
||||
tp_obj tp_strip(TP) {
|
||||
char const *v = TP_STR();
|
||||
int i, l = strlen(v); int a = l, b = 0;
|
||||
tp_obj r;
|
||||
char *s;
|
||||
for (i=0; i<l; i++) {
|
||||
if (v[i] != ' ' && v[i] != '\n' && v[i] != '\t' && v[i] != '\r') {
|
||||
a = _tp_min(a,i); b = _tp_max(b,i+1);
|
||||
}
|
||||
}
|
||||
if ((b-a) < 0) { return tp_string(""); }
|
||||
r = tp_string_t(tp,b-a);
|
||||
s = r.string.info->s;
|
||||
memcpy(s,v+a,b-a);
|
||||
return tp_track(tp,r);
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_replace(TP) {
|
||||
tp_obj s = TP_OBJ();
|
||||
tp_obj k = TP_OBJ();
|
||||
tp_obj v = TP_OBJ();
|
||||
tp_obj p = s;
|
||||
int i,n = 0;
|
||||
int c;
|
||||
int l;
|
||||
tp_obj rr;
|
||||
char *r;
|
||||
char *d;
|
||||
tp_obj z;
|
||||
while ((i = _tp_str_index(p,k)) != -1) {
|
||||
n += 1;
|
||||
p.string.val += i + k.string.len; p.string.len -= i + k.string.len;
|
||||
}
|
||||
/* fprintf(stderr,"ns: %d\n",n); */
|
||||
l = s.string.len + n * (v.string.len-k.string.len);
|
||||
rr = tp_string_t(tp,l);
|
||||
r = rr.string.info->s;
|
||||
d = r;
|
||||
z = p = s;
|
||||
while ((i = _tp_str_index(p,k)) != -1) {
|
||||
p.string.val += i; p.string.len -= i;
|
||||
memcpy(d,z.string.val,c=(p.string.val-z.string.val)); d += c;
|
||||
p.string.val += k.string.len; p.string.len -= k.string.len;
|
||||
memcpy(d,v.string.val,v.string.len); d += v.string.len;
|
||||
z = p;
|
||||
}
|
||||
memcpy(d,z.string.val,(s.string.val + s.string.len) - z.string.val);
|
||||
|
||||
return tp_track(tp,rr);
|
||||
}
|
||||
|
2
programs/develop/tinypy/tinypy/test.py
Normal file
2
programs/develop/tinypy/tinypy/test.py
Normal file
@ -0,0 +1,2 @@
|
||||
if __name__=="__main__":
|
||||
print("ok!")
|
750
programs/develop/tinypy/tinypy/tests.py
Normal file
750
programs/develop/tinypy/tinypy/tests.py
Normal file
@ -0,0 +1,750 @@
|
||||
# figure out if we're in python or tinypy (tinypy displays "1.0" as "1")
|
||||
is_tinypy = (str(1.0) == "1")
|
||||
if not is_tinypy:
|
||||
from boot import *
|
||||
|
||||
################################################################################
|
||||
RM = 'rm -f '
|
||||
VM = './vm '
|
||||
TINYPY = './tinypy '
|
||||
TMP = 'tmp.txt'
|
||||
if '-mingw32' in ARGV or "-win" in ARGV:
|
||||
RM = 'del '
|
||||
VM = 'vm '
|
||||
TINYPY = 'tinypy '
|
||||
TMP = 'tmp.txt'
|
||||
#TMP = 'stdout.txt'
|
||||
def system_rm(fname):
|
||||
system(RM+fname)
|
||||
|
||||
################################################################################
|
||||
#if not is_tinypy:
|
||||
#v = chksize()
|
||||
#assert (v < 65536)
|
||||
|
||||
################################################################################
|
||||
def t_show(t):
|
||||
if t.type == 'string': return '"'+t.val+'"'
|
||||
if t.type == 'number': return t.val
|
||||
if t.type == 'symbol': return t.val
|
||||
if t.type == 'name': return '$'+t.val
|
||||
return t.type
|
||||
def t_tokenize(s,exp=''):
|
||||
import tokenize
|
||||
result = tokenize.tokenize(s)
|
||||
res = ' '.join([t_show(t) for t in result])
|
||||
#print(s); print(exp); print(res)
|
||||
assert(res == exp)
|
||||
|
||||
if __name__ == '__main__':
|
||||
t_tokenize("234",'234')
|
||||
t_tokenize("234.234",'234.234')
|
||||
t_tokenize("phil",'$phil')
|
||||
t_tokenize("_phil234",'$_phil234')
|
||||
t_tokenize("'phil'",'"phil"')
|
||||
t_tokenize('"phil"','"phil"')
|
||||
t_tokenize("'phil' x",'"phil" $x')
|
||||
t_tokenize("#comment","")
|
||||
t_tokenize("and","and")
|
||||
t_tokenize("=","=")
|
||||
t_tokenize("()","( )")
|
||||
t_tokenize("(==)","( == )")
|
||||
t_tokenize("phil=234","$phil = 234")
|
||||
t_tokenize("a b","$a $b")
|
||||
t_tokenize("a\nb","$a nl $b")
|
||||
t_tokenize("a\n b","$a nl indent $b dedent")
|
||||
t_tokenize("a\n b\n c", "$a nl indent $b nl indent $c dedent dedent")
|
||||
t_tokenize("a\n b\n c", "$a nl indent $b nl $c dedent")
|
||||
t_tokenize("a\n b\n \n c", "$a nl indent $b nl nl indent $c dedent dedent")
|
||||
t_tokenize("a\n b\nc", "$a nl indent $b nl dedent $c")
|
||||
t_tokenize("a\n b\n c\nd", "$a nl indent $b nl indent $c nl dedent dedent $d")
|
||||
t_tokenize("(\n )","( )")
|
||||
t_tokenize(" x","indent $x dedent")
|
||||
t_tokenize(" #","")
|
||||
t_tokenize("None","None")
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
def t_lisp(t):
|
||||
if t.type == 'block':
|
||||
return """{%s}"""%' '.join([t_lisp(tt) for tt in t.items])
|
||||
if t.type == 'statement':
|
||||
return """%s;"""%' '.join([t_lisp(tt) for tt in t.items])
|
||||
if t.items == None: return t.val
|
||||
args = ''.join([" "+t_lisp(tt) for tt in t.items])
|
||||
return "("+t.val+args+")"
|
||||
|
||||
def t_parse(s,ex=''):
|
||||
import tokenize, parse
|
||||
r = ''
|
||||
tokens = tokenize.tokenize(s)
|
||||
tree = parse.parse(s,tokens)
|
||||
r = t_lisp(tree)
|
||||
#print(s); print(ex); print(r)
|
||||
assert(r==ex)
|
||||
|
||||
if __name__ == '__main__':
|
||||
t_parse('2+4*3', '(+ 2 (* 4 3))')
|
||||
t_parse('4*(2+3)', '(* 4 (+ 2 3))')
|
||||
t_parse('(2+3)*4', '(* (+ 2 3) 4)')
|
||||
t_parse('1<2', '(< 1 2)')
|
||||
t_parse('x=3', '(= x 3)')
|
||||
t_parse('x = 2*3', '(= x (* 2 3))')
|
||||
t_parse('x = y', '(= x y)')
|
||||
t_parse('2,3', '(, 2 3)')
|
||||
t_parse('2,3,4', '(, 2 3 4)')
|
||||
t_parse('[]', '([])')
|
||||
t_parse('[1]', '([] 1)')
|
||||
t_parse('[2,3,4]', '([] 2 3 4)')
|
||||
t_parse('print(3)', '($ print 3)')
|
||||
t_parse('print()', '($ print)')
|
||||
t_parse('print(2,3)', '($ print 2 3)')
|
||||
t_parse('def fnc():pass', '(def fnc (():) pass)')
|
||||
t_parse('def fnc(x):pass', '(def fnc ((): x) pass)')
|
||||
t_parse('def fnc(x,y):pass', '(def fnc ((): x y) pass)')
|
||||
t_parse('x\ny\nz', '(; x y z)')
|
||||
t_parse('return x', '(return x)')
|
||||
t_parse('print(test(2,3))', '($ print ($ test 2 3))')
|
||||
t_parse('x.y', '(. x y)')
|
||||
t_parse('get(2).x', '(. ($ get 2) x)')
|
||||
t_parse('{}', '({})')
|
||||
t_parse('True', 'True')
|
||||
t_parse('False', 'False')
|
||||
t_parse('None', 'None')
|
||||
t_parse('while 1:pass', '(while 1 pass)')
|
||||
t_parse('for x in y:pass', '(for x y pass)')
|
||||
t_parse('print("x")', '($ print x)')
|
||||
t_parse('if 1: pass', '(if (elif 1 pass))')
|
||||
t_parse('x = []', '(= x ([]))')
|
||||
t_parse('x[1]', '(. x 1)')
|
||||
t_parse('import sdl', '(import sdl)')
|
||||
t_parse('2 is 3', '(is 2 3)')
|
||||
t_parse('2 is not 3', '(isnot 2 3)')
|
||||
t_parse('x is None', '(is x None)')
|
||||
t_parse('2 is 3 or 4 is 5', '(or (is 2 3) (is 4 5))')
|
||||
t_parse('e.x == 3 or e.x == 4', '(or (== (. e x) 3) (== (. e x) 4))')
|
||||
t_parse('if 1==2: 3\nelif 4:5\nelse:6', '(if (elif (== 1 2) 3) (elif 4 5) (else 6))')
|
||||
t_parse('x = y(2)*3 + y(4)*5', '(= x (+ (* ($ y 2) 3) (* ($ y 4) 5)))')
|
||||
t_parse('x(1,2)+y(3,4)', '(+ ($ x 1 2) ($ y 3 4))')
|
||||
t_parse('x(a,b,c[d])', '($ x a b (. c d))')
|
||||
t_parse('x(1,2)*j+y(3,4)*k+z(5,6)*l', '(+ (+ (* ($ x 1 2) j) (* ($ y 3 4) k)) (* ($ z 5 6) l))')
|
||||
t_parse('a = b.x/c * 2 - 1', '(= a (- (* (/ (. b x) c) 2) 1))')
|
||||
t_parse('for x in y: z', '(for x y z)')
|
||||
|
||||
t_parse('min(255,n*2)','($ min 255 (* n 2))')
|
||||
t_parse('c = pal[i*8]','(= c (. pal (* i 8)))')
|
||||
t_parse('{x:y,a:b}','({} x y a b)')
|
||||
t_parse('x[1:2:3]','(. x (: 1 2 3))')
|
||||
if is_tinypy: t_parse('x - -234','(- x -234)')
|
||||
else: t_parse('x - -234','(- x -234.0)')
|
||||
t_parse('x - -y','(- x (- 0 y))')
|
||||
t_parse('x = ((y*4)-2)','(= x (- (* y 4) 2))')
|
||||
|
||||
if is_tinypy: t_parse('print([1,2,"OK",4][-3:3][1])','($ print (. (. ([] 1 2 OK 4) (: -3 3)) 1))')
|
||||
else: t_parse('print([1,2,"OK",4][-3:3][1])','($ print (. (. ([] 1 2 OK 4) (: -3.0 3)) 1))')
|
||||
|
||||
t_parse('a,b = 1,2','(= (, a b) (, 1 2))')
|
||||
t_parse('class C: pass','(class C (methods pass))')
|
||||
t_parse('def test(*v): pass','(def test ((): (* v)) pass)')
|
||||
t_parse('def test(**v): pass','(def test ((): (** v)) pass)')
|
||||
t_parse('test(*v)','($ test (* v))')
|
||||
t_parse('test(**v)','($ test (** v))')
|
||||
t_parse('def test(x=y): pass','(def test ((): (= x y)) pass)')
|
||||
t_parse('test(x=y)','($ test (= x y))')
|
||||
t_parse('def test(y="K",x="Z"): pass','(def test ((): (= y K) (= x Z)) pass)')
|
||||
t_parse('return x+y','(return (+ x y))')
|
||||
t_parse('if "a" is not "b": pass','(if (elif (isnot a b) pass))')
|
||||
t_parse('z = 0\nfor x in y: pass','(; (= z 0) (for x y pass))')
|
||||
t_parse('for k in {"OK":0}: pass','(for k ({} OK 0) pass)')
|
||||
t_parse('print(test(10,3,z=50000,*[200],**{"x":4000}))','($ print ($ test 10 3 (= z 50000) (* ([] 200)) (** ({} x 4000))))')
|
||||
t_parse('x="OK";print(x)','(; (= x OK) ($ print x))')
|
||||
t_parse('[(1,3)]','([] (, 1 3))')
|
||||
t_parse('x[:]','(. x (: None None))')
|
||||
t_parse('x[:1]','(. x (: None 1))')
|
||||
t_parse('x[1:]','(. x (: 1 None))')
|
||||
t_parse('return\nx','(; return x)')
|
||||
t_parse('"""test"""','test')
|
||||
t_parse('return a,b','(return (, a b))')
|
||||
|
||||
################################################################################
|
||||
|
||||
def showerror(cmd, ss, ex, res):
|
||||
print(cmd)
|
||||
print("ss : '" + str(ss) + "'")
|
||||
print("ex : '" + str(ex) + "'")
|
||||
print("res: '" + str(res) + "'")
|
||||
|
||||
def t_render(ss,ex,exact=True):
|
||||
import tokenize, parse, encode
|
||||
|
||||
if not istype(ss,'list'): ss =[ss]
|
||||
n = 1
|
||||
for s in ss:
|
||||
fname = 'tmp'+str(n)+'.tpc'
|
||||
system_rm(fname)
|
||||
tokens = tokenize.tokenize(s)
|
||||
t = parse.parse(s,tokens)
|
||||
r = encode.encode(fname,s,t)
|
||||
f = save(fname,r)
|
||||
n += 1
|
||||
system_rm('tmp.txt')
|
||||
cmd = VM + fname + " > tmp.txt"
|
||||
system(cmd)
|
||||
res = load(TMP).strip()
|
||||
#print(ss,ex,res)
|
||||
if exact:
|
||||
if res != ex: showerror(cmd, ss, ex, res)
|
||||
assert(res == ex)
|
||||
else:
|
||||
if ex not in res: showerror(cmd, ss, ex, res)
|
||||
assert(ex in res)
|
||||
|
||||
def test_range():
|
||||
t_render("""print(str(range(4))[:5])""","<list")
|
||||
t_render("""print(len(range(4)))""","4")
|
||||
t_render("""print(range(4)[0])""","0")
|
||||
t_render("""print(range(4)[1])""","1")
|
||||
t_render("""print(range(4)[-1])""","3")
|
||||
|
||||
t_render("""print(str(range(-4))[:5])""","<list")
|
||||
t_render("""print(len(range(-4)))""","0")
|
||||
|
||||
t_render("""print(str(range(0,5,3))[:5])""","<list")
|
||||
t_render("""print(len(range(0,5,3)))""","2")
|
||||
t_render("""print(range(0,5,3)[0])""","0")
|
||||
t_render("""print(range(0,5,3)[1])""","3")
|
||||
t_render("""print(range(0,5,3)[-1])""","3")
|
||||
|
||||
t_render("""print(str(range(5,0,-3))[:5])""","<list")
|
||||
t_render("""print(len(range(5,0,-3)))""","2")
|
||||
t_render("""print(range(5,0,-3)[0])""","5")
|
||||
t_render("""print(range(5,0,-3)[1])""","2")
|
||||
t_render("""print(range(5,0,-3)[-1])""","2")
|
||||
|
||||
t_render("""print(str(range(-8,-4))[:5])""","<list")
|
||||
t_render("""print(len(range(-8,-4)))""","4")
|
||||
t_render("""print(range(-8,-4)[0])""","-8")
|
||||
t_render("""print(range(-8,-4)[1])""","-7")
|
||||
t_render("""print(range(-8,-4)[-1])""","-5")
|
||||
|
||||
t_render("""print(str(range(-4,-8,-1))[:5])""","<list")
|
||||
t_render("""print(len(range(-4,-8,-1)))""","4")
|
||||
t_render("""print(range(-4,-8,-1)[0])""","-4")
|
||||
t_render("""print(range(-4,-8,-1)[1])""","-5")
|
||||
t_render("""print(range(-4,-8,-1)[-1])""","-7")
|
||||
|
||||
t_render("""print(str(range(-4,-8))[:5])""","<list")
|
||||
t_render("""print(len(range(-4,-8)))""","0")
|
||||
|
||||
t_render("""print(str(range(-8,-4,-1))[:5])""","<list")
|
||||
t_render("""print(len(range(-8,-4,-1)))""","0")
|
||||
|
||||
t_render("""print(str(range(0,4,0))[:5])""","<list")
|
||||
t_render("""print(len(range(0,4,0)))""","0")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
t_render('print("hello world")',"hello world")
|
||||
t_render('print(234)',"234")
|
||||
t_render('a=3\nprint(a)',"3")
|
||||
t_render('print(2+3)',"5")
|
||||
t_render("""
|
||||
x = 2
|
||||
x += 3
|
||||
print(x)
|
||||
"""
|
||||
,"5")
|
||||
t_render("""
|
||||
x = "OK"
|
||||
print(x)
|
||||
"""
|
||||
,"OK")
|
||||
t_render("""
|
||||
a,b = 1,2
|
||||
print(a+b)
|
||||
"""
|
||||
,"3")
|
||||
t_render("""
|
||||
x = 1
|
||||
if x == 1:
|
||||
print("yes")
|
||||
""","yes")
|
||||
t_render("""
|
||||
if 0 == 1:
|
||||
print("X")
|
||||
else:
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
if 0 == 1:
|
||||
print("X")
|
||||
elif 1 == 2:
|
||||
print("Y")
|
||||
else:
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
def test(x,y):
|
||||
return x+y
|
||||
r = test(3,5)
|
||||
print(r)
|
||||
""","8")
|
||||
t_render("""
|
||||
x = 1
|
||||
t = 0
|
||||
while x<=5:
|
||||
t = t+x
|
||||
x = x+1
|
||||
print(t)
|
||||
""","15")
|
||||
t_render("""
|
||||
x = {}
|
||||
x.y = "test"
|
||||
print(x.y)
|
||||
""","test")
|
||||
|
||||
t_render("""
|
||||
if "a" is "a":
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
if "a" is not "b":
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
if None is None:
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
t_render("""
|
||||
if "x" is "x" or "y" is "y":
|
||||
print("OK")
|
||||
"""
|
||||
,"OK")
|
||||
t_render("""
|
||||
x = 1
|
||||
while x < 3:
|
||||
break
|
||||
x = x + 1
|
||||
print(x)
|
||||
"""
|
||||
,"1")
|
||||
t_render("""
|
||||
x = 1
|
||||
n = 0
|
||||
while x < 10:
|
||||
x = x + 1
|
||||
if n == 2:
|
||||
continue
|
||||
n = n + 1
|
||||
print(n)
|
||||
"""
|
||||
,"2")
|
||||
t_render("""
|
||||
def test(x): return x
|
||||
y = test(1)*2 + test(3)*4 + test(5)*6
|
||||
print(y)
|
||||
"""
|
||||
,"44")
|
||||
t_render("""
|
||||
def test(a,b): return a+b
|
||||
print(test(1,1)+test(1,1))
|
||||
"""
|
||||
,"4")
|
||||
|
||||
t_render("""
|
||||
def test(): print("OK")
|
||||
x = test
|
||||
x()
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
x = [2,4,6]
|
||||
print(x[1])
|
||||
"""
|
||||
,"4")
|
||||
t_render("""
|
||||
def test(): print("OK")
|
||||
x = [1,test,2]
|
||||
x[1]()
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
|
||||
t_render("""
|
||||
z = 0
|
||||
for x in [1,2,3]:
|
||||
z += x
|
||||
print(z)
|
||||
"""
|
||||
,"6")
|
||||
|
||||
t_render("""
|
||||
z = 0
|
||||
for x in range(1,4):
|
||||
z += x
|
||||
print(z)
|
||||
"""
|
||||
,"6")
|
||||
|
||||
t_render("""
|
||||
x = {'a':'OK'}
|
||||
print(x.a)
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""print("1234"[1:3])""","23")
|
||||
t_render("""print("1234"[-3:3])""","23")
|
||||
t_render("""print([1,2,"OK",4][-3:3][1])""","OK")
|
||||
t_render("""
|
||||
n = 0
|
||||
for x in range(0,10,2):
|
||||
n += 1
|
||||
print(n)
|
||||
"""
|
||||
,"5")
|
||||
|
||||
t_render("""print(max(3,8,2,6))""","8")
|
||||
t_render("""print(min(3,4,2,6))""","2")
|
||||
t_render("""for k in {'OK':0}: print(k)""","OK")
|
||||
|
||||
t_render("""
|
||||
X = "OK"
|
||||
def test(): print(X)
|
||||
test()
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
a = 4
|
||||
def test(z):
|
||||
for i in range(0,a):
|
||||
z += i
|
||||
return z
|
||||
print(test(1))
|
||||
"""
|
||||
,"7")
|
||||
|
||||
t_render("""
|
||||
def test(self): print(self)
|
||||
fnc = bind(test,"OK")
|
||||
fnc()
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
class C:
|
||||
def __init__(self,data): self.data = data
|
||||
def print(self): print(self.data)
|
||||
C("OK").print()
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
t_render("""
|
||||
x = [v*v for v in range(0,5)]
|
||||
print(x[3])
|
||||
"""
|
||||
,"9")
|
||||
t_render("""
|
||||
t = [[y*10+x for x in range(0,10)] for y in range(0,10)]
|
||||
print(t[2][3])
|
||||
"""
|
||||
,"23")
|
||||
|
||||
t_render("""
|
||||
x = [1]
|
||||
x.extend([2,3])
|
||||
print(x[1])
|
||||
"""
|
||||
,"2")
|
||||
|
||||
#t_render("""
|
||||
#x = {'a':3}
|
||||
#merge(x,{'b':4})
|
||||
#print(x.b)
|
||||
#"""
|
||||
#,"4")
|
||||
|
||||
t_render("""
|
||||
x = [1,2,3]
|
||||
y = copy(x)
|
||||
y[0] *= 10
|
||||
print(x[0]+y[0])
|
||||
"""
|
||||
,"11")
|
||||
t_render("""
|
||||
x = {'a':3}
|
||||
y = copy(x)
|
||||
y.a *= 10
|
||||
print(x.a+y.a)
|
||||
"""
|
||||
,"33")
|
||||
t_render("""
|
||||
x = {}
|
||||
y = x['x']
|
||||
"""
|
||||
,'KeyError',0)
|
||||
t_render("""
|
||||
x = []
|
||||
y = x[1]
|
||||
"""
|
||||
,'KeyError',0)
|
||||
t_render("""print("O"+"K")""","OK")
|
||||
t_render("""print("-".join(["O","K"]))""","O-K")
|
||||
t_render("""print("OK-OK".split("-")[1])""","OK")
|
||||
t_render("""
|
||||
def test(*v): return max(v[2])
|
||||
print(test(*[1,2,"OK"]))
|
||||
"""
|
||||
,"OK")
|
||||
t_render("""
|
||||
def test(**v): return v['x']
|
||||
print(test(**{'x':'OK'}))
|
||||
"""
|
||||
,"OK")
|
||||
#t_render("""
|
||||
#def test(y='K',x='Z'): print(x+y)
|
||||
#test(x='O')
|
||||
#"""
|
||||
#,"OK")
|
||||
t_render("""
|
||||
def test(y='K',x='Z'): print(x+y)
|
||||
test('O')
|
||||
"""
|
||||
,"ZO")
|
||||
|
||||
#t_render("""
|
||||
#def test(a,b=2,*c,**d): return a+b+c[0]+d['x']+d['z']
|
||||
#print(test(10,3,z=50000,*[200],**{'x':4000}))
|
||||
#"""
|
||||
#,"54213")
|
||||
|
||||
t_render("""print("".join(["O"]+["K"]))""","OK")
|
||||
t_render("""x="OK";print(x)""","OK")
|
||||
t_render("""x = [1,2,] ; print(x[1])""","2")
|
||||
t_render("""a,b,d = [0],0,'OK'; print(d)""","OK")
|
||||
|
||||
t_render("""
|
||||
def test(): raise
|
||||
try:
|
||||
test()
|
||||
except:
|
||||
print("OK")
|
||||
""","OK")
|
||||
|
||||
t_render("""print("OKx"[:-1])""","OK")
|
||||
t_render("""print("xOK"[1:])""","OK")
|
||||
t_render("""a,b = "OK"; print(a+b)""","OK")
|
||||
|
||||
t_render("""
|
||||
def test(a,b):
|
||||
print a+b[2]
|
||||
test(1,3)
|
||||
""","Exception",False)
|
||||
|
||||
t_render("""
|
||||
def test(): raise
|
||||
test()
|
||||
""","Exception",False)
|
||||
|
||||
t_render(['OK="OK"',"import tmp1\nprint(tmp1.OK)"],"OK")
|
||||
|
||||
t_render(['O="O"','K="K"',"import tmp1, tmp2\nprint(tmp1.O+tmp2.K)"],"OK")
|
||||
|
||||
t_render("""
|
||||
def test(): return
|
||||
x = 1
|
||||
print(test())
|
||||
""","None")
|
||||
|
||||
t_render("""
|
||||
def test(): pass
|
||||
x = 1
|
||||
print(test())
|
||||
""","None")
|
||||
|
||||
t_render("""
|
||||
def test():
|
||||
global x
|
||||
x = "OK"
|
||||
test()
|
||||
print(x)
|
||||
""","OK")
|
||||
|
||||
t_render("""
|
||||
class X:
|
||||
pass
|
||||
y = X()
|
||||
print("OK")
|
||||
""","OK")
|
||||
|
||||
t_render("""
|
||||
class X: pass
|
||||
def test(): y = X()
|
||||
test()
|
||||
print("OK")
|
||||
""","OK")
|
||||
|
||||
t_render(["class X: pass\ndef test(): y = X()","import tmp1\ntmp1.test();print('OK')"],"OK")
|
||||
|
||||
t_render("print(len([1,2,3]))","3")
|
||||
|
||||
t_render('if not "?" in "xyz": print("OK")',"OK")
|
||||
|
||||
t_render('print({1:"OK"}[1])',"OK")
|
||||
|
||||
t_render('print(len("\0"))',"1")
|
||||
|
||||
t_render('print(1 in {1:2})',"1")
|
||||
|
||||
t_render('x = {1:2}; del x[1]; print(len(x))','0')
|
||||
|
||||
t_render("""
|
||||
def test(t):
|
||||
t = "O"+t
|
||||
print(t)
|
||||
test("K")
|
||||
""","OK")
|
||||
|
||||
t_render("""print([1,2,3].index(3))""","2")
|
||||
t_render("""print("1,2,3".split(",").index("3"))""","2")
|
||||
|
||||
t_render("""v = [3,2,1]; v.sort(); print(v[0])""","1")
|
||||
|
||||
t_render("""print(abs(-5))""","5")
|
||||
t_render("""print(int(1.234))""","1")
|
||||
|
||||
t_render("print(int(round(1.5)))","2")
|
||||
t_render("print(ord('X'))","88")
|
||||
t_render("print(ord(chr(128)))","128")
|
||||
#t_render("print(fsize('LICENSE.txt'))","181")
|
||||
t_render("print(int('ff',16))","255")
|
||||
t_render("""
|
||||
def test(x,y): print(x); return y
|
||||
test('a',1) or test('b',1) and test('c',0)
|
||||
""","a")
|
||||
|
||||
t_render("def test(): print('OK')\n{'__call__':test}()","OK")
|
||||
|
||||
t_render("""
|
||||
class A:
|
||||
def __init__(self):
|
||||
self.a = 'O'
|
||||
self.b = 'x'
|
||||
def test(self):
|
||||
print("KO")
|
||||
class B(A):
|
||||
def __init__(self):
|
||||
A.__init__(self)
|
||||
self.b = 'K'
|
||||
def test(self):
|
||||
print(self.a+self.b)
|
||||
B().test()
|
||||
""","OK")
|
||||
|
||||
t_render("""
|
||||
class A:
|
||||
def test(self):
|
||||
print(self)
|
||||
A.test("OK")
|
||||
""","OK")
|
||||
|
||||
t_render("""
|
||||
def test():
|
||||
def fnc():
|
||||
print("OK")
|
||||
fnc()
|
||||
test()
|
||||
""","OK")
|
||||
|
||||
t_render("""print("aa..bbb...ccc".replace("..","X"))""","aaXbbbX.ccc")
|
||||
t_render("""print("..bbb..".replace("..","X"))""","XbbbX")
|
||||
t_render("""print("234".replace("\r\n","\n"))""","234")
|
||||
t_render("""print("a\0b".replace("\0","X"))""","aXb")
|
||||
t_render("""x = "a\0b"; x = x.replace("\0","c"); print(x)""","acb")
|
||||
|
||||
t_render("""print(0xff)""","255")
|
||||
|
||||
t_render("""x=(1,3);print({x:'OK'}[x])""","OK")
|
||||
t_render("""x=(1,3);y=(1,3);print({x:'OK'}[y])""","OK")
|
||||
t_render("""print({(1,3):'OK'}[(1,3)])""","OK")
|
||||
t_render("def test(): test()\ntest()","Exception",0)
|
||||
t_render("x = []; x.append(x); print(x<x)","0");
|
||||
t_render("x = []; x.append(x); print({x:'OK'}[x])","OK")
|
||||
#t_render("print(float(str(4294967296))==float('4294967296'))","1")
|
||||
t_render("print(2**3)","8")
|
||||
#t_render("x = 'OK',\nprint(x[0])","OK")
|
||||
|
||||
test_range()
|
||||
|
||||
t_render(['v="OK"',"from tmp1 import *\nprint(v)"],"OK")
|
||||
t_render(['v="OK"',"from tmp1 import v\nprint(v)"],"OK")
|
||||
t_render(['x="X";y="K"',"x = 'O'\nfrom tmp1 import y\nprint(x+y)"],"OK")
|
||||
|
||||
t_render("""
|
||||
def test(**e):
|
||||
print(e['x'])
|
||||
test(x='OK')
|
||||
""","OK")
|
||||
|
||||
# test register allocator
|
||||
s = "def f():pass\n"+("f()\n"*256)+"print('OK')"
|
||||
t_render(s,"OK")
|
||||
|
||||
t_render("print(2**3)","8")
|
||||
t_render("print(2*3**2)", "18", False)
|
||||
|
||||
|
||||
t_render("""
|
||||
def test(**v): return 'OK'
|
||||
print(test())
|
||||
"""
|
||||
,"OK")
|
||||
t_render("""
|
||||
def test(**v):
|
||||
v['x'] = 'OK'
|
||||
return v
|
||||
print(test()['x'])
|
||||
"""
|
||||
,"OK")
|
||||
|
||||
################################################################################
|
||||
|
||||
def t_boot(ss,ex,exact=True):
|
||||
if not istype(ss,'list'): ss =[ss]
|
||||
n = 1
|
||||
for s in ss:
|
||||
fname = 'tmp'+str(n)+'.tpc'
|
||||
system_rm(fname)
|
||||
fname = 'tmp'+str(n)+'.py'
|
||||
save(fname,s)
|
||||
n += 1
|
||||
system_rm('tmp.txt')
|
||||
system(TINYPY+fname+' > tmp.txt')
|
||||
res = load(TMP).strip()
|
||||
#print(ss,ex,res)
|
||||
if exact: assert(res == ex)
|
||||
else: assert(ex in res)
|
||||
|
||||
is_boot = False
|
||||
try:
|
||||
assert(is_tinypy == True)
|
||||
x = compile('x=3','')
|
||||
is_boot = True
|
||||
except:
|
||||
pass
|
||||
|
||||
if is_boot == True and __name__ == '__main__':
|
||||
print("# t_boot")
|
||||
t_boot(["def test(): print('OK')","import tmp1; tmp1.test()"],"OK")
|
||||
|
171
programs/develop/tinypy/tinypy/tokenize.py
Normal file
171
programs/develop/tinypy/tinypy/tokenize.py
Normal file
@ -0,0 +1,171 @@
|
||||
class Token:
|
||||
def __init__(self,pos=(0,0),type='symbol',val=None,items=None):
|
||||
self.pos,self.type,self.val,self.items=pos,type,val,items
|
||||
|
||||
def u_error(ctx,s,i):
|
||||
y,x = i
|
||||
line = s.split('\n')[y-1]
|
||||
p = ''
|
||||
if y < 10: p += ' '
|
||||
if y < 100: p += ' '
|
||||
r = p + str(y) + ": " + line + "\n"
|
||||
r += " "+" "*x+"^" +'\n'
|
||||
raise 'error: '+ctx+'\n'+r
|
||||
|
||||
ISYMBOLS = '`-=[];,./~!@$%^&*()+{}:<>?'
|
||||
SYMBOLS = [
|
||||
'def','class','yield','return','pass','and','or','not','in','import',
|
||||
'is','while','break','for','continue','if','else','elif','try',
|
||||
'except','raise','True','False','None','global','del','from',
|
||||
'-','+','*','**','/','%','<<','>>',
|
||||
'-=','+=','*=','/=','=','==','!=','<','>',
|
||||
'<=','>=','[',']','{','}','(',')','.',':',',',';','&','|','!',
|
||||
]
|
||||
B_BEGIN,B_END = ['[','(','{'],[']',')','}']
|
||||
|
||||
class TData:
|
||||
def __init__(self):
|
||||
self.y,self.yi,self.nl = 1,0,True
|
||||
self.res,self.indent,self.braces = [],[0],0
|
||||
def add(self,t,v): self.res.append(Token(self.f,t,v))
|
||||
|
||||
def clean(s):
|
||||
s = s.replace('\r\n','\n')
|
||||
s = s.replace('\r','\n')
|
||||
return s
|
||||
|
||||
def tokenize(s):
|
||||
s = clean(s)
|
||||
try: return do_tokenize(s)
|
||||
except: u_error('tokenize',s,T.f)
|
||||
|
||||
def do_tokenize(s):
|
||||
global T
|
||||
T,i,l = TData(),0,len(s)
|
||||
T.f = (T.y,i-T.yi+1)
|
||||
while i < l:
|
||||
c = s[i]; T.f = (T.y,i-T.yi+1)
|
||||
if T.nl: T.nl = False; i = do_indent(s,i,l)
|
||||
elif c == '\n': i = do_nl(s,i,l)
|
||||
elif c in ISYMBOLS: i = do_symbol(s,i,l)
|
||||
elif c >= '0' and c <= '9': i = do_number(s,i,l)
|
||||
elif (c >= 'a' and c <= 'z') or \
|
||||
(c >= 'A' and c <= 'Z') or c == '_': i = do_name(s,i,l)
|
||||
elif c=='"' or c=="'": i = do_string(s,i,l)
|
||||
elif c=='#': i = do_comment(s,i,l)
|
||||
elif c == '\\' and s[i+1] == '\n':
|
||||
i += 2; T.y,T.yi = T.y+1,i
|
||||
elif c == ' ' or c == '\t': i += 1
|
||||
else: u_error('tokenize',s,T.f)
|
||||
indent(0)
|
||||
r = T.res; T = None
|
||||
return r
|
||||
|
||||
def do_nl(s,i,l):
|
||||
if not T.braces:
|
||||
T.add('nl',None)
|
||||
i,T.nl = i+1,True
|
||||
T.y,T.yi = T.y+1,i
|
||||
return i
|
||||
|
||||
def do_indent(s,i,l):
|
||||
v = 0
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if c != ' ' and c != '\t': break
|
||||
i,v = i+1,v+1
|
||||
if c != '\n' and c != '#' and not T.braces: indent(v)
|
||||
return i
|
||||
|
||||
def indent(v):
|
||||
if v == T.indent[-1]: pass
|
||||
elif v > T.indent[-1]:
|
||||
T.indent.append(v)
|
||||
T.add('indent',v)
|
||||
elif v < T.indent[-1]:
|
||||
n = T.indent.index(v)
|
||||
while len(T.indent) > n+1:
|
||||
v = T.indent.pop()
|
||||
T.add('dedent',v)
|
||||
|
||||
|
||||
def do_symbol(s,i,l):
|
||||
symbols = []
|
||||
v,f,i = s[i],i,i+1
|
||||
if v in SYMBOLS: symbols.append(v)
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if not c in ISYMBOLS: break
|
||||
v,i = v+c,i+1
|
||||
if v in SYMBOLS: symbols.append(v)
|
||||
v = symbols.pop(); n = len(v); i = f+n
|
||||
T.add('symbol',v)
|
||||
if v in B_BEGIN: T.braces += 1
|
||||
if v in B_END: T.braces -= 1
|
||||
return i
|
||||
|
||||
def do_number(s,i,l):
|
||||
v,i,c =s[i],i+1,s[i]
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if (c < '0' or c > '9') and (c < 'a' or c > 'f') and c != 'x': break
|
||||
v,i = v+c,i+1
|
||||
if c == '.':
|
||||
v,i = v+c,i+1
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if c < '0' or c > '9': break
|
||||
v,i = v+c,i+1
|
||||
T.add('number',v)
|
||||
return i
|
||||
|
||||
def do_name(s,i,l):
|
||||
v,i =s[i],i+1
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if (c < 'a' or c > 'z') and (c < 'A' or c > 'Z') and (c < '0' or c > '9') and c != '_': break
|
||||
v,i = v+c,i+1
|
||||
if v in SYMBOLS: T.add('symbol',v)
|
||||
else: T.add('name',v)
|
||||
return i
|
||||
|
||||
def do_string(s,i,l):
|
||||
v,q,i = '',s[i],i+1
|
||||
if (l-i) >= 5 and s[i] == q and s[i+1] == q: # """
|
||||
i += 2
|
||||
while i<l-2:
|
||||
c = s[i]
|
||||
if c == q and s[i+1] == q and s[i+2] == q:
|
||||
i += 3
|
||||
T.add('string',v)
|
||||
break
|
||||
else:
|
||||
v,i = v+c,i+1
|
||||
if c == '\n': T.y,T.yi = T.y+1,i
|
||||
else:
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if c == "\\":
|
||||
i = i+1; c = s[i]
|
||||
if c == "n": c = '\n'
|
||||
if c == "r": c = chr(13)
|
||||
if c == "t": c = "\t"
|
||||
if c == "0": c = "\0"
|
||||
v,i = v+c,i+1
|
||||
elif c == q:
|
||||
i += 1
|
||||
T.add('string',v)
|
||||
break
|
||||
else:
|
||||
v,i = v+c,i+1
|
||||
return i
|
||||
|
||||
def do_comment(s,i,l):
|
||||
i += 1
|
||||
while i<l:
|
||||
c = s[i]
|
||||
if c == '\n': break
|
||||
i += 1
|
||||
return i
|
||||
|
||||
|
32
programs/develop/tinypy/tinypy/tp.c
Normal file
32
programs/develop/tinypy/tinypy/tp.c
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef TP_COMPILER
|
||||
#define TP_COMPILER 1
|
||||
#endif
|
||||
|
||||
#include "tp.h"
|
||||
#include "list.c"
|
||||
#include "koconsole.c"
|
||||
#include "dict.c"
|
||||
#include "misc.c"
|
||||
#include "string.c"
|
||||
#include "builtins.c"
|
||||
#include "gc.c"
|
||||
#include "ops.c"
|
||||
void tp_compiler(TP);
|
||||
#include "vm.c"
|
||||
|
||||
tp_obj tp_None = {TP_NONE};
|
||||
|
||||
#if TP_COMPILER
|
||||
#include "bc.c"
|
||||
void tp_compiler(TP) {
|
||||
tp_import(tp,0,"tokenize",tp_tokenize);
|
||||
tp_import(tp,0,"parse",tp_parse);
|
||||
tp_import(tp,0,"encode",tp_encode);
|
||||
tp_import(tp,0,"py2bc",tp_py2bc);
|
||||
tp_call(tp,"py2bc","_init",tp_None);
|
||||
}
|
||||
#else
|
||||
void tp_compiler(TP) { }
|
||||
#endif
|
||||
|
||||
/**/
|
233
programs/develop/tinypy/tinypy/tp.h
Normal file
233
programs/develop/tinypy/tinypy/tp.h
Normal file
@ -0,0 +1,233 @@
|
||||
#ifndef TP_H
|
||||
#define TP_H
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef __USE_ISOC99
|
||||
#define __USE_ISOC99
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define tp_inline __inline__
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define tp_inline __inline
|
||||
#endif
|
||||
|
||||
#ifndef tp_inline
|
||||
#error "Unsuported compiler"
|
||||
#endif
|
||||
|
||||
#define tp_malloc(x) calloc((x),1)
|
||||
#define tp_realloc(x,y) realloc(x,y)
|
||||
#define tp_free(x) free(x)
|
||||
|
||||
/* #include <gc/gc.h>
|
||||
#define tp_malloc(x) GC_MALLOC(x)
|
||||
#define tp_realloc(x,y) GC_REALLOC(x,y)
|
||||
#define tp_free(x)*/
|
||||
|
||||
enum {
|
||||
TP_NONE,TP_NUMBER,TP_STRING,TP_DICT,
|
||||
TP_LIST,TP_FNC,TP_DATA,
|
||||
};
|
||||
|
||||
typedef double tp_num;
|
||||
|
||||
typedef struct tp_number_ {
|
||||
int type;
|
||||
tp_num val;
|
||||
} tp_number_;
|
||||
typedef struct tp_string_ {
|
||||
int type;
|
||||
struct _tp_string *info;
|
||||
char const *val;
|
||||
int len;
|
||||
} tp_string_;
|
||||
typedef struct tp_list_ {
|
||||
int type;
|
||||
struct _tp_list *val;
|
||||
} tp_list_;
|
||||
typedef struct tp_dict_ {
|
||||
int type;
|
||||
struct _tp_dict *val;
|
||||
} tp_dict_;
|
||||
typedef struct tp_fnc_ {
|
||||
int type;
|
||||
struct _tp_fnc *info;
|
||||
int ftype;
|
||||
void *val;
|
||||
} tp_fnc_;
|
||||
typedef struct tp_data_ {
|
||||
int type;
|
||||
struct _tp_data *info;
|
||||
void *val;
|
||||
int magic;
|
||||
} tp_data_;
|
||||
|
||||
typedef union tp_obj {
|
||||
int type;
|
||||
tp_number_ number;
|
||||
struct { int type; int *data; } gci;
|
||||
tp_string_ string;
|
||||
tp_dict_ dict;
|
||||
tp_list_ list;
|
||||
tp_fnc_ fnc;
|
||||
tp_data_ data;
|
||||
} tp_obj;
|
||||
|
||||
typedef struct _tp_string {
|
||||
int gci;
|
||||
char s[1];
|
||||
} _tp_string;
|
||||
typedef struct _tp_list {
|
||||
int gci;
|
||||
tp_obj *items;
|
||||
int len;
|
||||
int alloc;
|
||||
} _tp_list;
|
||||
typedef struct tp_item {
|
||||
int used;
|
||||
int hash;
|
||||
tp_obj key;
|
||||
tp_obj val;
|
||||
} tp_item;
|
||||
typedef struct _tp_dict {
|
||||
int gci;
|
||||
tp_item *items;
|
||||
int len;
|
||||
int alloc;
|
||||
int cur;
|
||||
int mask;
|
||||
int used;
|
||||
} _tp_dict;
|
||||
typedef struct _tp_fnc {
|
||||
int gci;
|
||||
tp_obj self;
|
||||
tp_obj globals;
|
||||
} _tp_fnc;
|
||||
|
||||
|
||||
typedef union tp_code {
|
||||
unsigned char i;
|
||||
struct { unsigned char i,a,b,c; } regs;
|
||||
struct { char val[4]; } string;
|
||||
struct { float val; } number;
|
||||
} tp_code;
|
||||
|
||||
typedef struct tp_frame_ {
|
||||
tp_code *codes;
|
||||
tp_code *cur;
|
||||
tp_code *jmp;
|
||||
tp_obj *regs;
|
||||
tp_obj *ret_dest;
|
||||
tp_obj fname;
|
||||
tp_obj name;
|
||||
tp_obj line;
|
||||
tp_obj globals;
|
||||
int lineno;
|
||||
int cregs;
|
||||
} tp_frame_;
|
||||
|
||||
#define TP_GCMAX 4096
|
||||
#define TP_FRAMES 256
|
||||
/* #define TP_REGS_PER_FRAME 256*/
|
||||
#define TP_REGS 16384
|
||||
typedef struct tp_vm {
|
||||
tp_obj builtins;
|
||||
tp_obj modules;
|
||||
tp_frame_ frames[TP_FRAMES];
|
||||
tp_obj _params;
|
||||
tp_obj params;
|
||||
tp_obj _regs;
|
||||
tp_obj *regs;
|
||||
tp_obj root;
|
||||
jmp_buf buf;
|
||||
int jmp;
|
||||
tp_obj ex;
|
||||
char chars[256][2];
|
||||
int cur;
|
||||
/* gc*/
|
||||
_tp_list *white;
|
||||
_tp_list *grey;
|
||||
_tp_list *black;
|
||||
_tp_dict *strings;
|
||||
int steps;
|
||||
} tp_vm;
|
||||
|
||||
#define TP tp_vm *tp
|
||||
typedef struct _tp_data {
|
||||
int gci;
|
||||
void (*free)(TP,tp_obj);
|
||||
} _tp_data;
|
||||
|
||||
/* NOTE: these are the few out of namespace items for convenience*/
|
||||
#define tp_True tp_number(1)
|
||||
#define tp_False tp_number(0)
|
||||
#define TP_CSTR(v) ((tp_str(tp,(v))).string.val)
|
||||
|
||||
extern tp_obj tp_None;
|
||||
|
||||
void tp_set(TP,tp_obj,tp_obj,tp_obj);
|
||||
tp_obj tp_get(TP,tp_obj,tp_obj);
|
||||
tp_obj tp_len(TP,tp_obj);
|
||||
tp_obj tp_str(TP,tp_obj);
|
||||
int tp_cmp(TP,tp_obj,tp_obj);
|
||||
void _tp_raise(TP,tp_obj);
|
||||
tp_obj tp_printf(TP,char const *fmt,...);
|
||||
tp_obj tp_track(TP,tp_obj);
|
||||
void tp_grey(TP,tp_obj);
|
||||
|
||||
/* __func__ __VA_ARGS__ __FILE__ __LINE__ */
|
||||
#define tp_raise(r,fmt,...) { \
|
||||
_tp_raise(tp,tp_printf(tp,fmt,__VA_ARGS__)); \
|
||||
return r; \
|
||||
}
|
||||
#define TP_OBJ() (tp_get(tp,tp->params,tp_None))
|
||||
tp_inline static tp_obj tp_type(TP,int t,tp_obj v) {
|
||||
if (v.type != t) { tp_raise(tp_None,"_tp_type(%d,%s)",t,TP_CSTR(v)); }
|
||||
return v;
|
||||
}
|
||||
#define TP_TYPE(t) tp_type(tp,t,TP_OBJ())
|
||||
#define TP_NUM() (TP_TYPE(TP_NUMBER).number.val)
|
||||
#define TP_STR() (TP_CSTR(TP_TYPE(TP_STRING)))
|
||||
#define TP_DEFAULT(d) (tp->params.list.val->len?tp_get(tp,tp->params,tp_None):(d))
|
||||
#define TP_LOOP(e) \
|
||||
int __l = tp->params.list.val->len; \
|
||||
int __i; for (__i=0; __i<__l; __i++) { \
|
||||
(e) = _tp_list_get(tp,tp->params.list.val,__i,"TP_LOOP");
|
||||
#define TP_END \
|
||||
}
|
||||
|
||||
tp_inline static int _tp_min(int a, int b) { return (a<b?a:b); }
|
||||
tp_inline static int _tp_max(int a, int b) { return (a>b?a:b); }
|
||||
tp_inline static int _tp_sign(tp_num v) { return (v<0?-1:(v>0?1:0)); }
|
||||
|
||||
tp_inline static tp_obj tp_number(tp_num v) {
|
||||
tp_obj val = {TP_NUMBER};
|
||||
val.number.val = v;
|
||||
return val;
|
||||
}
|
||||
|
||||
tp_inline static tp_obj tp_string(char const *v) {
|
||||
tp_obj val;
|
||||
tp_string_ s = {TP_STRING, 0, v, 0};
|
||||
s.len = strlen(v);
|
||||
val.string = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
tp_inline static tp_obj tp_string_n(char const *v,int n) {
|
||||
tp_obj val;
|
||||
tp_string_ s = {TP_STRING, 0,v,n};
|
||||
val.string = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
24
programs/develop/tinypy/tinypy/tpmain.c
Normal file
24
programs/develop/tinypy/tinypy/tpmain.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "tp.c"
|
||||
/* INCLUDE */
|
||||
const char header[]="TinyPy for kolibriOS";
|
||||
const int argc = 2;
|
||||
extern _stdcall void testmod_init(tp_vm *tp);
|
||||
void main(void) {
|
||||
char *argv[2]={"tpmain", "test.py"};
|
||||
|
||||
CONSOLE_INIT(header);
|
||||
con_printf("TinyPy console, version 1.1.\n");
|
||||
con_printf("Enter program file:");
|
||||
if (!(argv[1] = malloc(256)))
|
||||
con_printf("Memory error\n");
|
||||
con_gets(argv[1], 256);
|
||||
argv[1][strlen(argv[1]) - 1] = '\0';
|
||||
con_printf("Running file %s\n", argv[1]);
|
||||
tp_vm *tp = tp_init(argc, argv);
|
||||
/* INIT */
|
||||
tp_call(tp,"py2bc","tinypy",tp_None);
|
||||
tp_deinit(tp);
|
||||
return;
|
||||
}
|
||||
|
||||
/**/
|
380
programs/develop/tinypy/tinypy/vm.c
Normal file
380
programs/develop/tinypy/tinypy/vm.c
Normal file
@ -0,0 +1,380 @@
|
||||
|
||||
tp_vm *_tp_init(void) {
|
||||
int i;
|
||||
tp_vm *tp = (tp_vm*)tp_malloc(sizeof(tp_vm));
|
||||
tp->cur = 0;
|
||||
tp->jmp = 0;
|
||||
tp->ex = tp_None;
|
||||
tp->root = tp_list(0);
|
||||
for (i=0; i<256; i++) { tp->chars[i][0]=i; }
|
||||
tp_gc_init(tp);
|
||||
tp->_regs = tp_list(tp);
|
||||
for (i=0; i<TP_REGS; i++) { tp_set(tp,tp->_regs,tp_None,tp_None); }
|
||||
tp->builtins = tp_dict(tp);
|
||||
tp->modules = tp_dict(tp);
|
||||
tp->_params = tp_list(tp);
|
||||
for (i=0; i<TP_FRAMES; i++) { tp_set(tp,tp->_params,tp_None,tp_list(tp)); }
|
||||
tp_set(tp,tp->root,tp_None,tp->builtins);
|
||||
tp_set(tp,tp->root,tp_None,tp->modules);
|
||||
tp_set(tp,tp->root,tp_None,tp->_regs);
|
||||
tp_set(tp,tp->root,tp_None,tp->_params);
|
||||
tp_set(tp,tp->builtins,tp_string("MODULES"),tp->modules);
|
||||
tp_set(tp,tp->modules,tp_string("BUILTINS"),tp->builtins);
|
||||
tp_set(tp,tp->builtins,tp_string("BUILTINS"),tp->builtins);
|
||||
tp->regs = tp->_regs.list.val->items;
|
||||
tp_full(tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
void tp_deinit(TP) {
|
||||
while (tp->root.list.val->len) {
|
||||
_tp_list_pop(tp,tp->root.list.val,0,"tp_deinit");
|
||||
}
|
||||
tp_full(tp); tp_full(tp);
|
||||
tp_delete(tp,tp->root);
|
||||
tp_gc_deinit(tp);
|
||||
tp_free(tp);
|
||||
}
|
||||
|
||||
|
||||
/* tp_frame_*/
|
||||
void tp_frame(TP,tp_obj globals,tp_code *codes,tp_obj *ret_dest) {
|
||||
tp_frame_ f;
|
||||
f.globals = globals;
|
||||
f.codes = codes;
|
||||
f.cur = f.codes;
|
||||
f.jmp = 0;
|
||||
/* fprintf(stderr,"tp->cur: %d\n",tp->cur);*/
|
||||
f.regs = (tp->cur <= 0?tp->regs:tp->frames[tp->cur].regs+tp->frames[tp->cur].cregs);
|
||||
f.ret_dest = ret_dest;
|
||||
f.lineno = 0;
|
||||
f.line = tp_string("");
|
||||
f.name = tp_string("?");
|
||||
f.fname = tp_string("?");
|
||||
f.cregs = 0;
|
||||
/* return f;*/
|
||||
if (f.regs+256 >= tp->regs+TP_REGS || tp->cur >= TP_FRAMES-1) { tp_raise(,"tp_frame: stack overflow %d",tp->cur); }
|
||||
tp->cur += 1;
|
||||
tp->frames[tp->cur] = f;
|
||||
}
|
||||
|
||||
void _tp_raise(TP,tp_obj e) {
|
||||
if (!tp || !tp->jmp) {
|
||||
con_printf("\nException:\n%s\n",TP_CSTR(e));
|
||||
exit(-1);
|
||||
return;
|
||||
}
|
||||
if (e.type != TP_NONE) { tp->ex = e; }
|
||||
tp_grey(tp,e);
|
||||
longjmp(tp->buf,1);
|
||||
}
|
||||
|
||||
void tp_print_stack(TP) {
|
||||
int i;
|
||||
con_printf("\n");
|
||||
for (i=0; i<=tp->cur; i++) {
|
||||
if (!tp->frames[i].lineno) { continue; }
|
||||
con_printf("File \"%s\", line %d, in %s\n %s\n",
|
||||
TP_CSTR(tp->frames[i].fname),tp->frames[i].lineno,
|
||||
TP_CSTR(tp->frames[i].name),TP_CSTR(tp->frames[i].line));
|
||||
}
|
||||
con_printf("\nException:\n%s\n",TP_CSTR(tp->ex));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tp_handle(TP) {
|
||||
int i;
|
||||
for (i=tp->cur; i>=0; i--) {
|
||||
if (tp->frames[i].jmp) { break; }
|
||||
}
|
||||
if (i >= 0) {
|
||||
tp->cur = i;
|
||||
tp->frames[i].cur = tp->frames[i].jmp;
|
||||
tp->frames[i].jmp = 0;
|
||||
return;
|
||||
}
|
||||
tp_print_stack(tp);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void _tp_call(TP,tp_obj *dest, tp_obj fnc, tp_obj params) {
|
||||
/*con_printf("_tp_call %s %s\n",TP_CSTR(fnc), TP_CSTR(params));*/
|
||||
if (fnc.type == TP_DICT) {
|
||||
_tp_call(tp,dest,tp_get(tp,fnc,tp_string("__call__")),params);
|
||||
return;
|
||||
}
|
||||
if (fnc.type == TP_FNC && !(fnc.fnc.ftype&1)) {
|
||||
*dest = _tp_tcall(tp,fnc);
|
||||
tp_grey(tp,*dest);
|
||||
return;
|
||||
}
|
||||
if (fnc.type == TP_FNC) {
|
||||
tp_frame(tp,fnc.fnc.info->globals,(tp_code*)fnc.fnc.val,dest);
|
||||
if ((fnc.fnc.ftype&2)) {
|
||||
tp->frames[tp->cur].regs[0] = params;
|
||||
_tp_list_insert(tp,params.list.val,0,fnc.fnc.info->self);
|
||||
} else {
|
||||
tp->frames[tp->cur].regs[0] = params;
|
||||
}
|
||||
return;
|
||||
}
|
||||
tp_params_v(tp,1,fnc); tp_print(tp);
|
||||
tp_raise(,"tp_call: %s is not callable",TP_CSTR(fnc));
|
||||
}
|
||||
|
||||
|
||||
void tp_return(TP, tp_obj v) {
|
||||
tp_obj *dest = tp->frames[tp->cur].ret_dest;
|
||||
if (dest) { *dest = v; tp_grey(tp,v); }
|
||||
/* memset(tp->frames[tp->cur].regs,0,TP_REGS_PER_FRAME*sizeof(tp_obj));
|
||||
fprintf(stderr,"regs:%d\n",(tp->frames[tp->cur].cregs+1));*/
|
||||
memset(tp->frames[tp->cur].regs,0,tp->frames[tp->cur].cregs*sizeof(tp_obj));
|
||||
tp->cur -= 1;
|
||||
}
|
||||
|
||||
enum {
|
||||
TP_IEOF,TP_IADD,TP_ISUB,TP_IMUL,TP_IDIV,TP_IPOW,TP_IAND,TP_IOR,TP_ICMP,TP_IGET,TP_ISET,
|
||||
TP_INUMBER,TP_ISTRING,TP_IGGET,TP_IGSET,TP_IMOVE,TP_IDEF,TP_IPASS,TP_IJUMP,TP_ICALL,
|
||||
TP_IRETURN,TP_IIF,TP_IDEBUG,TP_IEQ,TP_ILE,TP_ILT,TP_IDICT,TP_ILIST,TP_INONE,TP_ILEN,
|
||||
TP_ILINE,TP_IPARAMS,TP_IIGET,TP_IFILE,TP_INAME,TP_INE,TP_IHAS,TP_IRAISE,TP_ISETJMP,
|
||||
TP_IMOD,TP_ILSH,TP_IRSH,TP_IITER,TP_IDEL,TP_IREGS,
|
||||
TP_ITOTAL
|
||||
};
|
||||
|
||||
/* char *tp_strings[TP_ITOTAL] = {
|
||||
"EOF","ADD","SUB","MUL","DIV","POW","AND","OR","CMP","GET","SET","NUM",
|
||||
"STR","GGET","GSET","MOVE","DEF","PASS","JUMP","CALL","RETURN","IF","DEBUG",
|
||||
"EQ","LE","LT","DICT","LIST","NONE","LEN","LINE","PARAMS","IGET","FILE",
|
||||
"NAME","NE","HAS","RAISE","SETJMP","MOD","LSH","RSH","ITER","DEL","REGS",
|
||||
};*/
|
||||
|
||||
#define VA ((int)e.regs.a)
|
||||
#define VB ((int)e.regs.b)
|
||||
#define VC ((int)e.regs.c)
|
||||
#define RA regs[e.regs.a]
|
||||
#define RB regs[e.regs.b]
|
||||
#define RC regs[e.regs.c]
|
||||
#define UVBC (unsigned short)(((VB<<8)+VC))
|
||||
#define SVBC (short)(((VB<<8)+VC))
|
||||
#define GA tp_grey(tp,RA)
|
||||
#define SR(v) f->cur = cur; return(v);
|
||||
|
||||
int tp_step(TP) {
|
||||
tp_frame_ *f = &tp->frames[tp->cur];
|
||||
tp_obj *regs = f->regs;
|
||||
tp_code *cur = f->cur;
|
||||
while(1) {
|
||||
tp_code e = *cur;
|
||||
/* fprintf(stderr,"%2d.%4d: %-6s %3d %3d %3d\n",tp->cur,cur-f->codes,tp_strings[e.i],VA,VB,VC);
|
||||
int i; for(i=0;i<16;i++) { fprintf(stderr,"%d: %s\n",i,TP_CSTR(regs[i])); }*/
|
||||
switch (e.i) {
|
||||
case TP_IEOF: tp_return(tp,tp_None); SR(0); break;
|
||||
case TP_IADD: RA = tp_add(tp,RB,RC); break;
|
||||
case TP_ISUB: RA = tp_sub(tp,RB,RC); break;
|
||||
case TP_IMUL: RA = tp_mul(tp,RB,RC); break;
|
||||
case TP_IDIV: RA = tp_div(tp,RB,RC); break;
|
||||
case TP_IPOW: RA = tp_pow(tp,RB,RC); break;
|
||||
case TP_IAND: RA = tp_and(tp,RB,RC); break;
|
||||
case TP_IOR: RA = tp_or(tp,RB,RC); break;
|
||||
case TP_IMOD: RA = tp_mod(tp,RB,RC); break;
|
||||
case TP_ILSH: RA = tp_lsh(tp,RB,RC); break;
|
||||
case TP_IRSH: RA = tp_rsh(tp,RB,RC); break;
|
||||
case TP_ICMP: RA = tp_number(tp_cmp(tp,RB,RC)); break;
|
||||
case TP_INE: RA = tp_number(tp_cmp(tp,RB,RC)!=0); break;
|
||||
case TP_IEQ: RA = tp_number(tp_cmp(tp,RB,RC)==0); break;
|
||||
case TP_ILE: RA = tp_number(tp_cmp(tp,RB,RC)<=0); break;
|
||||
case TP_ILT: RA = tp_number(tp_cmp(tp,RB,RC)<0); break;
|
||||
case TP_IPASS: break;
|
||||
case TP_IIF: if (tp_bool(tp,RA)) { cur += 1; } break;
|
||||
case TP_IGET: RA = tp_get(tp,RB,RC); GA; break;
|
||||
case TP_IITER:
|
||||
if (RC.number.val < tp_len(tp,RB).number.val) {
|
||||
RA = tp_iter(tp,RB,RC); GA;
|
||||
RC.number.val += 1;
|
||||
cur += 1;
|
||||
}
|
||||
break;
|
||||
case TP_IHAS: RA = tp_has(tp,RB,RC); break;
|
||||
case TP_IIGET: tp_iget(tp,&RA,RB,RC); break;
|
||||
case TP_ISET: tp_set(tp,RA,RB,RC); break;
|
||||
case TP_IDEL: tp_del(tp,RA,RB); break;
|
||||
case TP_IMOVE: RA = RB; break;
|
||||
case TP_INUMBER:
|
||||
RA = tp_number(*(tp_num*)(*++cur).string.val);
|
||||
cur += sizeof(tp_num)/4;
|
||||
continue;
|
||||
case TP_ISTRING:
|
||||
RA = tp_string_n((*(cur+1)).string.val,UVBC);
|
||||
cur += (UVBC/4)+1;
|
||||
break;
|
||||
case TP_IDICT: RA = tp_dict_n(tp,VC/2,&RB); break;
|
||||
case TP_ILIST: RA = tp_list_n(tp,VC,&RB); break;
|
||||
case TP_IPARAMS: RA = tp_params_n(tp,VC,&RB); break;
|
||||
case TP_ILEN: RA = tp_len(tp,RB); break;
|
||||
case TP_IJUMP: cur += SVBC; continue; break;
|
||||
case TP_ISETJMP: f->jmp = cur+SVBC; break;
|
||||
case TP_ICALL: _tp_call(tp,&RA,RB,RC); cur++; SR(0); break;
|
||||
case TP_IGGET:
|
||||
if (!tp_iget(tp,&RA,f->globals,RB)) {
|
||||
RA = tp_get(tp,tp->builtins,RB); GA;
|
||||
}
|
||||
break;
|
||||
case TP_IGSET: tp_set(tp,f->globals,RA,RB); break;
|
||||
case TP_IDEF:
|
||||
RA = tp_def(tp,(*(cur+1)).string.val,f->globals);
|
||||
cur += SVBC; continue;
|
||||
break;
|
||||
case TP_IRETURN: tp_return(tp,RA); SR(0); break;
|
||||
case TP_IRAISE: _tp_raise(tp,RA); SR(0); break;
|
||||
case TP_IDEBUG:
|
||||
tp_params_v(tp,3,tp_string("DEBUG:"),tp_number(VA),RA); tp_print(tp);
|
||||
break;
|
||||
case TP_INONE: RA = tp_None; break;
|
||||
case TP_ILINE:
|
||||
f->line = tp_string_n((*(cur+1)).string.val,VA*4-1);
|
||||
/* fprintf(stderr,"%7d: %s\n",UVBC,f->line.string.val);*/
|
||||
cur += VA; f->lineno = UVBC;
|
||||
break;
|
||||
case TP_IFILE: f->fname = RA; break;
|
||||
case TP_INAME: f->name = RA; break;
|
||||
case TP_IREGS: f->cregs = VA; break;
|
||||
default: tp_raise(0,"tp_step: invalid instruction %d",e.i); break;
|
||||
}
|
||||
cur += 1;
|
||||
}
|
||||
SR(0);
|
||||
}
|
||||
|
||||
void tp_run(TP,int cur) {
|
||||
if (tp->jmp) {
|
||||
tp_raise(,"tp_run(%d) called recusively",cur);
|
||||
}
|
||||
tp->jmp = 1;
|
||||
if (setjmp(tp->buf))
|
||||
{
|
||||
tp_handle(tp);
|
||||
}
|
||||
while (tp->cur >= cur && tp_step(tp) != -1);
|
||||
tp->cur = cur-1;
|
||||
tp->jmp = 0;
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_call(TP, const char *mod, const char *fnc, tp_obj params) {
|
||||
tp_obj tmp;
|
||||
tp_obj r = tp_None;
|
||||
tmp = tp_get(tp,tp->modules,tp_string(mod));
|
||||
tmp = tp_get(tp,tmp,tp_string(fnc));
|
||||
_tp_call(tp,&r,tmp,params);
|
||||
tp_run(tp,tp->cur);
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj tp_import(TP, char const *fname, char const *name, void *codes) {
|
||||
tp_obj code = tp_None;
|
||||
tp_obj g;
|
||||
if (!((fname && strstr(fname,".tpc")) || codes)) {
|
||||
return tp_call(tp,"py2bc","import_fname",tp_params_v(tp,2,tp_string(fname),tp_string(name)));
|
||||
}
|
||||
if (!codes) {
|
||||
tp_params_v(tp,1,tp_string(fname));
|
||||
code = tp_load(tp);
|
||||
/* We cast away the constness. */
|
||||
codes = (void *)code.string.val;
|
||||
} else {
|
||||
code = tp_data(tp,0,codes);
|
||||
}
|
||||
|
||||
g = tp_dict(tp);
|
||||
tp_set(tp,g,tp_string("__name__"),tp_string(name));
|
||||
tp_set(tp,g,tp_string("__code__"),code);
|
||||
tp_set(tp,g,tp_string("__dict__"),g);
|
||||
tp_frame(tp,g,(tp_code*)codes,0);
|
||||
tp_set(tp,tp->modules,tp_string(name),g);
|
||||
if (!tp->jmp) {
|
||||
tp_run(tp,tp->cur);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tp_obj tp_exec_(TP) {
|
||||
tp_obj code = TP_OBJ();
|
||||
tp_obj globals = TP_OBJ();
|
||||
tp_frame(tp,globals,(tp_code*)code.string.val,0);
|
||||
return tp_None;
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_import_(TP) {
|
||||
tp_obj mod = TP_OBJ();
|
||||
char const *s;
|
||||
tp_obj r;
|
||||
|
||||
if (tp_has(tp,tp->modules,mod).number.val) {
|
||||
return tp_get(tp,tp->modules,mod);
|
||||
}
|
||||
|
||||
s = TP_CSTR(mod);
|
||||
r = tp_import(tp,TP_CSTR(tp_add(tp,mod,tp_string(".tpc"))),s,0);
|
||||
return r;
|
||||
}
|
||||
|
||||
void tp_builtins(TP) {
|
||||
struct {const char *s;void *f;} b[] = {
|
||||
{"print",tp_print}, {"range",tp_range}, {"min",tp_min},
|
||||
{"max",tp_max}, {"bind",tp_bind}, {"copy",tp_copy},
|
||||
{"import",tp_import_}, {"len",tp_len_}, {"assert",tp_assert},
|
||||
{"str",tp_str2}, {"float",tp_float}, {"system",tp_system},
|
||||
{"istype",tp_istype}, {"chr",tp_chr}, {"save",tp_save},
|
||||
{"load",tp_load}, {"fpack",tp_fpack}, {"abs",tp_abs},
|
||||
{"int",tp_int}, {"exec",tp_exec_}, {"exists",tp_exists},
|
||||
{"mtime",tp_mtime}, {"number",tp_float}, {"round",tp_round},
|
||||
{"ord",tp_ord}, {"merge",tp_merge}, {"syscall", tp_syscall}, {0,0},
|
||||
};
|
||||
int i; for(i=0; b[i].s; i++) {
|
||||
tp_set(tp,tp->builtins,tp_string(b[i].s),tp_fnc(tp,(tp_obj (*)(tp_vm *))b[i].f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void tp_args(TP,int argc, char *argv[]) {
|
||||
tp_obj self = tp_list(tp);
|
||||
int i;
|
||||
for (i=1; i<argc; i++) { _tp_list_append(tp,self.list.val,tp_string(argv[i])); }
|
||||
tp_set(tp,tp->builtins,tp_string("ARGV"),self);
|
||||
}
|
||||
|
||||
|
||||
tp_obj tp_main(TP,char *fname, void *code) {
|
||||
return tp_import(tp,fname,"__main__",code);
|
||||
}
|
||||
tp_obj tp_compile(TP, tp_obj text, tp_obj fname) {
|
||||
return tp_call(tp,"BUILTINS","compile",tp_params_v(tp,2,text,fname));
|
||||
}
|
||||
|
||||
tp_obj tp_exec(TP,tp_obj code, tp_obj globals) {
|
||||
tp_obj r=tp_None;
|
||||
tp_frame(tp,globals,(tp_code*)code.string.val,&r);
|
||||
tp_run(tp,tp->cur);
|
||||
return r;
|
||||
}
|
||||
|
||||
tp_obj tp_eval(TP, char *text, tp_obj globals) {
|
||||
tp_obj code = tp_compile(tp,tp_string(text),tp_string("<eval>"));
|
||||
return tp_exec(tp,code,globals);
|
||||
}
|
||||
|
||||
tp_vm *tp_init(int argc, char *argv[]) {
|
||||
tp_vm *tp = _tp_init();
|
||||
tp_builtins(tp);
|
||||
tp_args(tp,argc,argv);
|
||||
tp_compiler(tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
||||
/**/
|
9
programs/develop/tinypy/tinypy/vmmain.c
Normal file
9
programs/develop/tinypy/tinypy/vmmain.c
Normal file
@ -0,0 +1,9 @@
|
||||
#define TP_COMPILER 0
|
||||
#include "tp.c"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
tp_vm *tp = tp_init(argc,argv);
|
||||
tp_import(tp,argv[1],"__main__",0);
|
||||
tp_deinit(tp);
|
||||
return(0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user