Uploaded tinypy sources.

git-svn-id: svn://kolibrios.org@1913 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
jaeger 2011-03-31 09:59:54 +00:00
parent 00ac1c33b5
commit 9fd32b8cdf
34 changed files with 9410 additions and 0 deletions

View 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

View 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.
================================================================================

View 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.

View 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

View 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()

View 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);
}

View 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)

View 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")

View 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));
}
/**/

View 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()

View 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 .

File diff suppressed because it is too large Load Diff

View 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()

View 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);
}

View 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;
}

View 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)

View 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;
}
/**/

View 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));
}

View 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);

View 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;
}

View 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;
}

View 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;
}
/**/

View 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));
/**/

View 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

View 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])

View 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);
}

View File

@ -0,0 +1,2 @@
if __name__=="__main__":
print("ok!")

View 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")

View 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

View 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
/**/

View 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

View 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;
}
/**/

View 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;
}
/**/

View 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);
}