Merge remote-tracking branch 'upstream/master' into list_index

This commit is contained in:
John R. Lenton 2014-01-05 01:57:54 +00:00
commit 7e73a8fd09
63 changed files with 11043 additions and 410 deletions

97
logo/FONT-LICENSE.txt Normal file
View File

@ -0,0 +1,97 @@
The font used for the Micro Python logo is "Exo",
http://www.google.com/fonts/specimen/Exo.
Copyright (c) 2013, Natanael Gama (https://plus.google.com/u/0/+NatanaelGama),
with Reserved Font Name Exo.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

9888
logo/vector-text-R2000.dxf Normal file

File diff suppressed because it is too large Load Diff

137
logo/vector-text.svg Normal file
View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="765.09967"
height="158.82559"
id="svg2">
<defs
id="defs4">
<symbol
id="*Paper_Space" />
<symbol
id="*Model_Space" />
<pattern
height="8"
id="Hatch"
patternUnits="userSpaceOnUse"
width="8"
x="0"
y="0">
<path
d="M8 4 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3030" />
<path
d="M6 2 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3032" />
<path
d="M4 0 l-4,4"
linecap="square"
stroke="#000000"
stroke-width="0.25"
id="path3034" />
</pattern>
<marker
refX="0"
refY="0"
orient="auto"
id="DistanceX"
style="overflow:visible">
<path
d="M 3,-3 -3,3 M 0,-5 0,5"
id="path3027"
style="stroke:#000000;stroke-width:0.5" />
</marker>
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-463.61971,-103.98436)"
id="layer1">
<g
transform="translate(474.11971,-800.05225)"
id="g3038" />
<path
d="m 474.11971,216.99105 8.38645,-95.79752 25.49501,0 15.95818,65.41468 15.86248,-65.41468 25.39886,0 8.91346,95.79752 -18.06677,0 -6.32579,-64.02471 -15.43095,64.02471 -20.41521,0 -16.10201,-64.02471 -5.60688,64.02471 -18.06683,0 0,0 z"
id="path3042"
style="fill:none;stroke:#bebebe" />
<path
d="m 585.06082,216.99105 0,-69.48774 18.35416,0 0,69.48774 -18.35416,0 0,0 z"
id="path3044"
style="fill:none;stroke:#bebebe" />
<path
d="m 584.4376,137.15201 0,-11.54959 a 3.667629,3.667629 0 0 1 0.77873,-2.55179 3.012482,3.012482 0 0 1 2.33617,-0.85049 l 13.75388,0 a 2.665344,2.665344 0 0 1 2.15675,0.85049 3.874957,3.874957 0 0 1 0.71861,2.55179 l 0,11.54959 a 3.170925,3.170925 0 0 1 -0.71861,2.2641 2.844672,2.844672 0 0 1 -2.15675,0.7548 l -13.75388,0 a 3.183373,3.183373 0 0 1 -2.27606,-0.79069 2.91442,2.91442 0 0 1 -0.83884,-2.22821 l 0,0 z"
id="path3046"
style="fill:none;stroke:#bebebe" />
<path
d="m 614.10181,182.15117 a 104.76828,104.76828 0 0 1 0.4073,-9.62042 61.45992,61.45992 0 0 1 1.22222,-7.96728 34.257292,34.257292 0 0 1 2.02456,-6.2896 18.589823,18.589823 0 0 1 2.81556,-4.58861 18.372489,18.372489 0 0 1 7.1404,-5.29557 25.178476,25.178476 0 0 1 9.29684,-1.55745 139.56012,139.56012 0 0 1 17.5877,1.01826 80.33883,80.33883 0 0 1 14.32895,3.05509 l 0,10.97421 a 913.84864,913.84864 0 0 0 -25.74636,0.0659 25.765381,25.765381 0 0 0 -2.98332,0.19783 10.614363,10.614363 0 0 0 -3.33051,1.29399 5.904958,5.904958 0 0 0 -2.63582,3.23482 31.868466,31.868466 0 0 0 -1.36576,6.43958 73.360882,73.360882 0 0 0 -0.45546,8.67975 97.248263,97.248263 0 0 0 0.31162,8.4166 30.406975,30.406975 0 0 0 0.93453,5.64883 13.352632,13.352632 0 0 0 1.53966,3.54027 6.228032,6.228032 0 0 0 2.12638,2.09068 9.932543,9.932543 0 0 0 3.12103,1.0243 26.061579,26.061579 0 0 0 4.52268,0.3415 252.7863,252.7863 0 0 0 21.37366,-0.9105 l 3.49828,-0.2876 0,11.5494 a 31.724353,31.724353 0 0 1 -11.74129,3.6421 158.5758,158.5758 0 0 1 -14.80802,0.8147 l -0.76677,0 a 36.794709,36.794709 0 0 1 -14.74822,-1.7372 18.781067,18.781067 0 0 1 -7.00851,-5.2116 19.357438,19.357438 0 0 1 -2.91432,-4.6785 33.943497,33.943497 0 0 1 -2.0816,-6.31978 60.236572,60.236572 0 0 1 -1.24921,-7.96117 102.18754,102.18754 0 0 1 -0.4162,-9.60257 l 0,0 z"
id="path3048"
style="fill:none;stroke:#bebebe" />
<path
d="m 679.80386,216.99105 0,-69.48774 15.43095,0 2.87536,8.76962 a 37.96926,37.96926 0 0 1 9.88418,-7.0806 23.135088,23.135088 0 0 1 10.0038,-2.36009 49.347494,49.347494 0 0 1 4.75639,0.19169 12.434249,12.434249 0 0 1 2.95909,0.57507 l 0,17.68339 a 99.917807,99.917807 0 0 0 -9.91977,-0.38338 37.215466,37.215466 0 0 0 -5.73876,0.4073 21.894431,21.894431 0 0 0 -4.66069,1.22222 14.160958,14.160958 0 0 0 -3.88165,2.33617 19.705025,19.705025 0 0 0 -3.40259,3.74978 l 0,44.37657 -18.30631,0 0,0 z"
id="path3050"
style="fill:none;stroke:#bebebe" />
<path
d="m 754.27554,165.28239 a 101.69692,101.69692 0 0 0 -2.0126,9.66857 52.999906,52.999906 0 0 0 -0.67107,7.91912 69.045724,69.045724 0 0 0 0.67107,10.97428 16.561755,16.561755 0 0 0 0.94036,3.45043 8.854315,8.854315 0 0 0 1.47954,2.49198 7.551397,7.551397 0 0 0 3.97766,2.53988 27.363959,27.363959 0 0 0 6.03841,0.5272 45.079768,45.079768 0 0 0 5.70257,-0.2636 9.767782,9.767782 0 0 0 3.66696,-1.3179 5.86791,5.86791 0 0 0 2.53952,-3.2587 27.050263,27.050263 0 0 0 1.25749,-5.53508 55.730735,55.730735 0 0 0 0.42019,-7.21251 158.11284,158.11284 0 0 0 -0.31284,-11.78882 30.217313,30.217313 0 0 0 -1.10107,-6.30187 5.911226,5.911226 0 0 0 -2.51499,-3.57004 10.986507,10.986507 0 0 0 -3.58967,-1.47372 21.310199,21.310199 0 0 0 -4.82232,-0.49134 57.038011,57.038011 0 0 0 -4.65456,0.16194 17.096194,17.096194 0 0 0 -3.08484,0.4852 7.14005,7.14005 0 0 0 -3.92981,2.99498 l 0,0 z"
id="path3052"
style="fill:none;stroke:#bebebe" />
<path
d="m 733.28556,183.589 a 92.623124,92.623124 0 0 1 1.03022,-15.09572 34.923348,34.923348 0 0 1 3.25874,-10.35129 16.997543,16.997543 0 0 1 6.15803,-6.70918 27.334986,27.334986 0 0 1 8.92573,-3.45043 58.555226,58.555226 0 0 1 12.30409,-1.15014 64.576878,64.576878 0 0 1 8.27122,0.49134 39.74236,39.74236 0 0 1 6.88921,1.47341 24.998971,24.998971 0 0 1 5.51149,2.4561 17.713605,17.713605 0 0 1 4.12825,3.43847 20.147183,20.147183 0 0 1 3.00878,4.6935 33.054914,33.054914 0 0 1 2.15,6.2209 56.120992,56.120992 0 0 1 1.28816,7.7486 92.689443,92.689443 0 0 1 0.42939,9.27599 93.582889,93.582889 0 0 1 -0.42325,9.252 55.494869,55.494869 0 0 1 -1.2667,7.67662 31.745279,31.745279 0 0 1 -2.11013,6.10108 18.697304,18.697304 0 0 1 -2.95663,4.5258 17.025604,17.025604 0 0 1 -4.09145,3.2707 25.393667,25.393667 0 0 1 -5.51762,2.3362 41.865621,41.865621 0 0 1 -6.94227,1.4018 69.328567,69.328567 0 0 1 -8.36845,0.4672 63.054282,63.054282 0 0 1 -8.23963,-0.5002 39.37126,39.37126 0 0 1 -6.89197,-1.5006 25.293848,25.293848 0 0 1 -5.544,-2.5009 18.401937,18.401937 0 0 1 -4.19634,-3.5014 20.408256,20.408256 0 0 1 -2.97719,-4.5227 30.962036,30.962036 0 0 1 -2.12639,-5.85256 49.71676,49.71676 0 0 1 -1.2762,-7.18239 79.250711,79.250711 0 0 1 -0.42509,-8.5122 l 0,0 z"
id="path3054"
style="fill:none;stroke:#bebebe" />
<path
d="m 848.06104,137.39155 -21.46935,0 0,28.03468 21.37427,0 a 9.641122,9.641122 0 0 0 5.07904,-1.19799 6.289092,6.289092 0 0 0 1.92917,-1.80311 10.492988,10.492988 0 0 0 1.37711,-2.82139 28.324879,28.324879 0 0 0 1.10107,-8.69815 26.4065,26.4065 0 0 0 -0.58581,-5.91236 12.140086,12.140086 0 0 0 -1.76048,-4.22332 7.47549,7.47549 0 0 0 -2.93517,-2.5337 9.405207,9.405207 0 0 0 -4.10985,-0.84466 l 0,0 z"
id="path3070"
style="fill:none;stroke:#ff0000" />
<path
d="m 957.94734,161.35288 0,-10.20776 11.26221,-3.78566 3.01798,-19.36075 15.28924,0 0,19.36075 15.57453,0 0,13.99342 -15.57453,0 0,27.89084 a 42.025479,42.025479 0 0 0 0.35885,5.97244 12.328486,12.328486 0 0 0 1.07653,3.82783 8.288976,8.288976 0 0 0 4.45643,3.95366 211.85149,211.85149 0 0 0 6.12183,2.0487 14.600045,14.600045 0 0 0 2.64989,0.6828 l 0,11.2619 -15.95782,0 a 16.804947,16.804947 0 0 1 -7.44373,-1.5545 13.606965,13.606965 0 0 1 -5.31827,-4.6635 22.537606,22.537606 0 0 1 -3.18973,-7.7724 49.35507,49.35507 0 0 1 -1.0612,-10.88151 l 0,-30.76626 -11.26221,0 0,0 z"
id="path3072"
style="fill:none;stroke:#ff0000" />
<path
d="m 1197.4165,146.30501 a 24.952696,24.952696 0 0 1 9.1,1.52157 16.077531,16.077531 0 0 1 6.4991,4.56469 19.935463,19.935463 0 0 1 3.8982,7.60782 39.066225,39.066225 0 0 1 1.3004,10.65064 l 0,46.34132 -18.3042,0 0,-46.58086 a 15.801149,15.801149 0 0 0 -0.4845,-4.1304 7.859179,7.859179 0 0 0 -1.4446,-2.95019 5.977282,5.977282 0 0 0 -2.4138,-1.77 8.891394,8.891394 0 0 0 -3.3738,-0.5901 25.71484,25.71484 0 0 0 -8.9373,1.36576 29.528311,29.528311 0 0 0 -7.8364,4.67234 l 0,49.98345 -18.3072,0 0,-69.48774 14.6667,0 3.6405,7.42778 a 71.772372,71.772372 0 0 1 8.5663,-5.43911 24.453688,24.453688 0 0 1 6.6248,-2.5159 31.484828,31.484828 0 0 1 6.8058,-0.67107 l 0,0 z"
id="path3074"
style="fill:none;stroke:#ff0000" />
<path
d="m 882.47028,147.50331 19.21508,0 12.07804,48.68928 a 6.616536,6.616536 0 0 0 2.23895,3.70202 6.560409,6.560409 0 0 0 4.13438,1.23404 2.645525,2.645525 0 0 0 0.52754,0.1437 l 13.89681,-53.76904 19.11999,0 -24.10395,91.48424 -9.53546,13.3224 -13.13312,0 9.82377,-35.3189 a 22.713351,22.713351 0 0 1 -7.27505,-1.1052 17.518915,17.518915 0 0 1 -5.86726,-3.3157 20.440644,20.440644 0 0 1 -4.4595,-5.5261 32.678904,32.678904 0 0 1 -3.05171,-7.73647 l -13.60851,-51.80427 0,0 z"
id="path3076"
style="fill:none;stroke:#ff0000" />
<path
d="m 1011.86,216.99105 0,-102.50669 18.163,0 0,40.44673 a 72.12737,72.12737 0 0 1 8.5172,-5.39126 25.732974,25.732974 0 0 1 6.6739,-2.56375 33.530661,33.530661 0 0 1 6.95,-0.67107 24.944515,24.944515 0 0 1 9.0968,1.52157 16.082612,16.082612 0 0 1 6.5022,4.56469 19.935463,19.935463 0 0 1 3.8982,7.60782 39.066225,39.066225 0 0 1 1.3004,10.65064 l 0,46.34132 -18.3072,0 0,-46.58086 a 15.799795,15.799795 0 0 0 -0.4815,-4.1304 7.862409,7.862409 0 0 0 -1.4477,-2.95019 5.972344,5.972344 0 0 0 -2.4107,-1.77 8.899237,8.899237 0 0 0 -3.3768,-0.5901 25.71484,25.71484 0 0 0 -8.9374,1.36576 29.519786,29.519786 0 0 0 -7.8332,4.67234 l 0,49.98345 -18.3072,0 0,0 z"
id="path3078"
style="fill:none;stroke:#ff0000" />
<path
d="m 1082.7855,183.589 a 92.623252,92.623252 0 0 1 1.0305,-15.09572 34.921866,34.921866 0 0 1 3.2572,-10.35129 16.998317,16.998317 0 0 1 6.1587,-6.70918 27.333351,27.333351 0 0 1 8.9251,-3.45043 58.559567,58.559567 0 0 1 12.305,-1.15014 64.58165,64.58165 0 0 1 8.2718,0.49134 39.738976,39.738976 0 0 1 6.8886,1.47341 24.998971,24.998971 0 0 1 5.5115,2.4561 17.713605,17.713605 0 0 1 4.1283,3.43847 20.147183,20.147183 0 0 1 3.0088,4.6935 33.054914,33.054914 0 0 1 2.15,6.2209 56.120992,56.120992 0 0 1 1.2881,7.7486 92.689443,92.689443 0 0 1 0.4294,9.27599 93.581477,93.581477 0 0 1 -0.4202,9.252 55.498435,55.498435 0 0 1 -1.2697,7.67662 31.745279,31.745279 0 0 1 -2.1102,6.10108 18.697304,18.697304 0 0 1 -2.9566,4.5258 17.025604,17.025604 0 0 1 -4.0914,3.2707 25.393667,25.393667 0 0 1 -5.5177,2.3362 41.856735,41.856735 0 0 1 -6.9407,1.4018 69.341232,69.341232 0 0 1 -8.37,0.4672 63.04259,63.04259 0 0 1 -8.2381,-0.5002 39.369587,39.369587 0 0 1 -6.8917,-1.5006 25.298499,25.298499 0 0 1 -5.5452,-2.5009 18.400351,18.400351 0 0 1 -4.1957,-3.5014 20.410163,20.410163 0 0 1 -2.9781,-4.5227 30.960474,30.960474 0 0 1 -2.1255,-5.85256 49.716395,49.716395 0 0 1 -1.2759,-7.18239 79.251281,79.251281 0 0 1 -0.4263,-8.5122 l 0,0 z"
id="path3080"
style="fill:none;stroke:#ff0000" />
<path
d="m 1103.7764,165.28239 a 101.69564,101.69564 0 0 0 -2.012,9.66857 53.000252,53.000252 0 0 0 -0.6717,7.91912 69.045959,69.045959 0 0 0 0.6717,10.97428 16.559516,16.559516 0 0 0 0.9385,3.45043 8.857186,8.857186 0 0 0 1.4814,2.49198 7.547675,7.547675 0 0 0 3.9749,2.53988 27.366717,27.366717 0 0 0 6.039,0.5272 45.096704,45.096704 0 0 0 5.7048,-0.2636 9.763441,9.763441 0 0 0 3.6651,-1.3179 5.86791,5.86791 0 0 0 2.5395,-3.2587 27.050263,27.050263 0 0 0 1.2575,-5.53508 55.730735,55.730735 0 0 0 0.4202,-7.21251 158.11284,158.11284 0 0 0 -0.3129,-11.78882 30.217313,30.217313 0 0 0 -1.101,-6.30187 5.911226,5.911226 0 0 0 -2.515,-3.57004 10.983294,10.983294 0 0 0 -3.5885,-1.47372 21.319589,21.319589 0 0 0 -4.8244,-0.49134 57.015487,57.015487 0 0 0 -4.6528,0.16194 17.099511,17.099511 0 0 0 -3.0854,0.4852 7.138992,7.138992 0 0 0 -3.9289,2.99498 l 0,0 z"
id="path3082"
style="fill:none;stroke:#ff0000" />
<path
d="m 808.23539,216.99105 0,-95.79752 41.2641,0 a 34.14365,34.14365 0 0 1 12.2774,1.98899 19.541659,19.541659 0 0 1 8.37612,5.96633 23.907413,23.907413 0 0 1 4.41962,8.9975 48.211674,48.211674 0 0 1 1.47525,12.61539 51.335387,51.335387 0 0 1 -1.77276,14.40103 37.898378,37.898378 0 0 1 -1.96598,5.31336 19.829803,19.829803 0 0 1 -2.34936,3.91172 16.201726,16.201726 0 0 1 -6.46841,4.88796 26.614618,26.614618 0 0 1 -11.40636,2.39628 143.35618,143.35618 0 0 1 -14.75865,-1.19799 519.68963,519.68963 0 0 1 -7.78724,-0.95876 24.527385,24.527385 0 0 1 -2.94743,-0.47907 l 0,37.95478 -18.3563,0 0,0 z"
id="path3084"
style="fill:none;stroke:#ff0000" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -7,6 +7,9 @@
#include "mpconfig.h"
#include "asmthumb.h"
// wrapper around everything in this file
#if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
#define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
@ -447,3 +450,5 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
asm_thumb_write_op16(as, OP_SVC(fun_id));
}
}
#endif // MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB

View File

@ -6,6 +6,10 @@
#include "misc.h"
#include "asmx64.h"
#include "mpconfig.h"
// wrapper around everything in this file
#if MICROPY_EMIT_X64
#if defined(__OpenBSD__) || defined(__MACH__)
#define MAP_ANONYMOUS MAP_ANON
@ -620,3 +624,5 @@ void asm_x64_call_ind(asm_x64_t* as, void *ptr, int temp_r64) {
asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
*/
}
#endif // MICROPY_EMIT_X64

View File

@ -1,12 +1,16 @@
// Micro Python byte-codes.
// The comment at the end of the line (if it exists) tells the arguments to the byte-code.
#define MP_BC_LOAD_CONST_FALSE (0x10)
#define MP_BC_LOAD_CONST_NONE (0x11)
#define MP_BC_LOAD_CONST_TRUE (0x12)
#define MP_BC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
#define MP_BC_LOAD_CONST_INT (0x14) // qstr
#define MP_BC_LOAD_CONST_DEC (0x15) // qstr
#define MP_BC_LOAD_CONST_ID (0x16) // qstr
#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
#define MP_BC_LOAD_CONST_ELLIPSIS (0x13)
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // 24-bit, in excess
#define MP_BC_LOAD_CONST_INT (0x15) // qstr
#define MP_BC_LOAD_CONST_DEC (0x16) // qstr
#define MP_BC_LOAD_CONST_ID (0x17) // qstr
#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr
#define MP_BC_LOAD_CONST_STRING (0x19) // qstr
#define MP_BC_LOAD_FAST_0 (0x20)
#define MP_BC_LOAD_FAST_1 (0x21)

View File

@ -8,6 +8,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -87,14 +88,6 @@ mp_obj_t mp_builtin_any(mp_obj_t o_in) {
return mp_const_false;
}
mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
if (mp_obj_is_callable(o_in)) {
return mp_const_true;
@ -103,42 +96,6 @@ mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
}
}
#if MICROPY_ENABLE_FLOAT
mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args) {
assert(0 <= n_args && n_args <= 2);
if (n_args == 0) {
return mp_obj_new_complex(0, 0);
} else if (n_args == 1) {
// TODO allow string as first arg and parse it
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
return args[0];
} else {
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
}
} else {
mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
mp_obj_get_complex(args[0], &real, &imag);
} else {
real = mp_obj_get_float(args[0]);
imag = 0;
}
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
mp_float_t real2, imag2;
mp_obj_get_complex(args[1], &real2, &imag2);
real -= imag2;
imag += real2;
} else {
imag += mp_obj_get_float(args[1]);
}
return mp_obj_new_complex(real, imag);
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_complex_obj, 0, 2, mp_builtin_complex);
#endif
mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
int ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
@ -147,15 +104,10 @@ mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
str[1] = '\0';
return mp_obj_new_str(qstr_from_str_take(str, 2));
} else {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)"));
}
}
mp_obj_t mp_builtin_dict(void) {
// TODO create from an iterable!
return rt_build_map(0);
}
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
@ -165,29 +117,10 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args);
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
}
}
#if MICROPY_ENABLE_FLOAT
static mp_obj_t mp_builtin_float(int n_args, const mp_obj_t *args) {
assert(0 <= n_args && n_args <= 1);
if (n_args == 0) {
return mp_obj_new_float(0);
} else {
// TODO allow string as arg and parse it
if (MP_OBJ_IS_TYPE(args[0], &float_type)) {
return args[0];
} else {
return mp_obj_new_float(mp_obj_get_float(args[0]));
}
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_float_obj, 0, 1, mp_builtin_float);
#endif
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
// TODO hash will generally overflow small integer; can we safely truncate it?
return mp_obj_new_int(mp_obj_hash(o_in));
@ -195,23 +128,6 @@ static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
static mp_obj_t mp_builtin_int(int n_args, const mp_obj_t *args) {
assert(0 <= n_args && n_args <= 2);
if (n_args == 0) {
return MP_OBJ_NEW_SMALL_INT(0);
} else if (n_args == 1) {
// TODO if arg is a string then parse it
return mp_obj_new_int(mp_obj_get_int(args[0]));
} else { // n_args == 2
// TODO, parse with given base
assert(0);
return MP_OBJ_NEW_SMALL_INT(0);
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_int_obj, 0, 2, mp_builtin_int);
static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
return rt_getiter(o_in);
}
@ -235,29 +151,11 @@ mp_obj_t mp_builtin_len(mp_obj_t o_in) {
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
len = mp_obj_dict_len(o_in);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
}
return MP_OBJ_NEW_SMALL_INT(len);
}
mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0: return rt_build_list(0, NULL);
case 1:
{
// make list from iterable
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t list = rt_build_list(0, NULL);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
rt_list_append(list, item);
}
return list;
}
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
@ -270,7 +168,7 @@ mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
}
}
if (max_obj == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence"));
}
return max_obj;
} else {
@ -297,7 +195,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
}
}
if (min_obj == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence"));
}
return min_obj;
} else {
@ -315,7 +213,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
static mp_obj_t mp_builtin_next(mp_obj_t o) {
mp_obj_t ret = rt_iternext(o);
if (ret == mp_const_stop_iteration) {
nlr_jump(mp_obj_new_exception(qstr_from_str_static("StopIteration")));
nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration));
} else {
return ret;
}
@ -328,7 +226,7 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
if (strlen(str) == 1) {
return mp_obj_new_int(str[0]);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str)));
}
}
@ -336,7 +234,7 @@ mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]);
case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
@ -362,36 +260,16 @@ mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) {
case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1);
case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1);
case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
static mp_obj_t mp_builtin_set(int n_args, const mp_obj_t *args) {
assert(0 <= n_args && n_args <= 1);
if (n_args == 0) {
// return a new, empty set
return mp_obj_new_set(0, NULL);
} else {
// 1 argument, an iterable from which we make a new set
mp_obj_t set = mp_obj_new_set(0, NULL);
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
mp_obj_set_store(set, item);
}
return set;
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_obj, 0, 1, mp_builtin_set);
mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
mp_obj_t value;
switch (n_args) {
case 1: value = mp_obj_new_int(0); break;
case 2: value = args[1]; break;
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args));
}
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
@ -404,8 +282,7 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
static mp_obj_t mp_builtin_type(mp_obj_t o_in) {
// TODO implement the 3 argument version of type()
if (MP_OBJ_IS_SMALL_INT(o_in)) {
// TODO implement int-type
return mp_const_none;
return (mp_obj_t)&int_type;
} else {
mp_obj_base_t *o = o_in;
return (mp_obj_t)o->type;

View File

@ -58,7 +58,9 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
return mp_const_none;
}
if (!mp_compile(pn, false)) {
mp_obj_t module_fun = mp_compile(pn, false);
if (module_fun == mp_const_none) {
// TODO handle compile error correctly
rt_locals_set(old_locals);
rt_globals_set(old_globals);
@ -66,7 +68,6 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
}
// complied successfully, execute it
mp_obj_t module_fun = rt_make_function_from_id(1); // TODO we should return from mp_compile the unique_code_id for the module
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
rt_call_function_0(module_fun);

View File

@ -7,6 +7,7 @@
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
@ -38,20 +39,6 @@ typedef enum {
#define EMIT_OPT_ASM_THUMB (4)
typedef struct _compiler_t {
qstr qstr___class__;
qstr qstr___locals__;
qstr qstr___name__;
qstr qstr___module__;
qstr qstr___qualname__;
qstr qstr___doc__;
qstr qstr_assertion_error;
qstr qstr_micropython;
qstr qstr_byte_code;
qstr qstr_native;
qstr qstr_viper;
qstr qstr_asm_thumb;
qstr qstr_range;
bool is_repl;
pass_kind_t pass;
bool had_error; // try to keep compiler clean from nlr
@ -202,7 +189,7 @@ static int comp_next_label(compiler_t *comp) {
}
static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options);
scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(), emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
@ -903,7 +890,7 @@ qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint
// returns true if it was a built-in decorator (even if the built-in had an error)
static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) {
if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
return false;
}
@ -913,16 +900,16 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
}
qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
if (attr == comp->qstr_byte_code) {
if (attr == MP_QSTR_byte_code) {
*emit_options = EMIT_OPT_BYTE_CODE;
#if MICROPY_EMIT_NATIVE
} else if (attr == comp->qstr_native) {
} else if (attr == MP_QSTR_native) {
*emit_options = EMIT_OPT_NATIVE_PYTHON;
} else if (attr == comp->qstr_viper) {
} else if (attr == MP_QSTR_viper) {
*emit_options = EMIT_OPT_VIPER;
#endif
#if MICROPY_EMIT_INLINE_THUMB
} else if (attr == comp->qstr_asm_thumb) {
} else if (attr == MP_QSTR_asm_thumb) {
*emit_options = EMIT_OPT_ASM_THUMB;
#endif
} else {
@ -1329,7 +1316,7 @@ void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
int l_end = comp_next_label(comp);
c_if_cond(comp, pns->nodes[0], true, l_end);
EMIT(load_id, comp->qstr_assertion_error);
EMIT(load_id, MP_QSTR_AssertionError);
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
// assertion message
compile_node(comp, pns->nodes[1]);
@ -1495,7 +1482,7 @@ void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
// for viper it will be much, much faster
if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) {
mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
mp_parse_node_t *args;
int n_args = list_get(&pn_range_args, PN_arglist, &args);
@ -1743,7 +1730,7 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
// for REPL, evaluate then print the expression
EMIT(load_id, qstr_from_str_static("__repl_print__"));
EMIT(load_id, MP_QSTR___repl_print__);
compile_node(comp, pns->nodes[0]);
EMIT(call_function, 1, 0, false, false);
EMIT(pop_top);
@ -2683,7 +2670,7 @@ void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
if (kind == MP_PARSE_NODE_STRING) {
compile_node(comp, pns->nodes[0]); // a doc string
// store doc string
EMIT(store_id, comp->qstr___doc__);
EMIT(store_id, MP_QSTR___doc__);
}
}
}
@ -2796,35 +2783,35 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
if (comp->pass == PASS_1) {
bool added;
id_info_t *id_info = scope_find_or_add_id(scope, comp->qstr___class__, &added);
id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
assert(added);
id_info->kind = ID_INFO_KIND_LOCAL;
id_info = scope_find_or_add_id(scope, comp->qstr___locals__, &added);
id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
assert(added);
id_info->kind = ID_INFO_KIND_LOCAL;
id_info->param = true;
scope->num_params = 1; // __locals__ is the parameter
}
EMIT(load_id, comp->qstr___locals__);
EMIT(load_id, MP_QSTR___locals__);
EMIT(store_locals);
EMIT(load_id, comp->qstr___name__);
EMIT(store_id, comp->qstr___module__);
EMIT(load_id, MP_QSTR___name__);
EMIT(store_id, MP_QSTR___module__);
EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
EMIT(store_id, comp->qstr___qualname__);
EMIT(store_id, MP_QSTR___qualname__);
check_for_doc_string(comp, pns->nodes[2]);
compile_node(comp, pns->nodes[2]); // 2 is class body
id_info_t *id = scope_find(scope, comp->qstr___class__);
id_info_t *id = scope_find(scope, MP_QSTR___class__);
assert(id != NULL);
if (id->kind == ID_INFO_KIND_LOCAL) {
EMIT(load_const_tok, MP_TOKEN_KW_NONE);
} else {
#if MICROPY_EMIT_CPYTHON
EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num
EMIT(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
#else
EMIT(load_fast, comp->qstr___class__, 0); // XXX check this is the correct local num
EMIT(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num
#endif
}
EMIT(return_value);
@ -2917,7 +2904,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
scope->num_locals = 0;
for (int i = 0; i < scope->id_info_len; i++) {
id_info_t *id = &scope->id_info[i];
if (scope->kind == SCOPE_CLASS && id->qstr == comp->qstr___class__) {
if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
// __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
continue;
}
@ -3021,20 +3008,6 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
compiler_t *comp = m_new(compiler_t, 1);
comp->qstr___class__ = qstr_from_str_static("__class__");
comp->qstr___locals__ = qstr_from_str_static("__locals__");
comp->qstr___name__ = qstr_from_str_static("__name__");
comp->qstr___module__ = qstr_from_str_static("__module__");
comp->qstr___qualname__ = qstr_from_str_static("__qualname__");
comp->qstr___doc__ = qstr_from_str_static("__doc__");
comp->qstr_assertion_error = qstr_from_str_static("AssertionError");
comp->qstr_micropython = qstr_from_str_static("micropython");
comp->qstr_byte_code = qstr_from_str_static("byte_code");
comp->qstr_native = qstr_from_str_static("native");
comp->qstr_viper = qstr_from_str_static("viper");
comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb");
comp->qstr_range = qstr_from_str_static("range");
comp->is_repl = is_repl;
comp->had_error = false;
@ -3048,10 +3021,10 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
pn = fold_constants(pn);
// set the outer scope
scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
// compile pass 1
comp->emit = emit_pass1_new(comp->qstr___class__);
comp->emit = emit_pass1_new(MP_QSTR___class__);
comp->emit_method_table = &emit_pass1_method_table;
comp->emit_inline_asm = NULL;
comp->emit_inline_asm_method_table = NULL;
@ -3083,11 +3056,13 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
// compile pass 2 and 3
#if !MICROPY_EMIT_CPYTHON
emit_t *emit_bc = NULL;
#if MICROPY_EMIT_NATIVE
emit_t *emit_native = NULL;
#endif
#if MICROPY_EMIT_INLINE_THUMB
emit_inline_asm_t *emit_inline_thumb = NULL;
#endif
#endif // !MICROPY_EMIT_CPYTHON
for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
if (false) {
// dummy
@ -3115,6 +3090,8 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit_method_table = &emit_cpython_method_table;
#else
switch (s->emit_options) {
#if MICROPY_EMIT_NATIVE
case EMIT_OPT_NATIVE_PYTHON:
case EMIT_OPT_VIPER:
#if MICROPY_EMIT_X64
@ -3131,6 +3108,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit = emit_native;
comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
break;
#endif // MICROPY_EMIT_NATIVE
default:
if (emit_bc == NULL) {
@ -3140,7 +3118,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
comp->emit_method_table = &emit_bc_method_table;
break;
}
#endif
#endif // !MICROPY_EMIT_CPYTHON
// compile pass 2 and pass 3
compile_scope(comp, s, PASS_2);
@ -3157,10 +3135,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
} else {
#if MICROPY_EMIT_CPYTHON
// can't create code, so just return true
(void)module_scope; // to suppress warning that module_scope is unused
return mp_const_true;
#else
// return function that executes the outer module
return rt_make_function_from_id(1);
return rt_make_function_from_id(module_scope->unique_code_id);
#endif
}
}

View File

@ -249,6 +249,7 @@ static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break;
case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break;
case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break;
case MP_TOKEN_ELLIPSIS: emit_write_byte_1(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
default: assert(0);
}
}

View File

@ -13,6 +13,7 @@
#include "runtime0.h"
#include "emit.h"
// wrapper around everything in this file
#if MICROPY_EMIT_CPYTHON
struct _emit_t {

View File

@ -34,7 +34,7 @@
#include "runtime.h"
// wrapper around everything in this file
#if N_X64 || N_THUMB
#if (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
#if N_X64
@ -1319,4 +1319,4 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_yield_from,
};
#endif // N_X64 || N_THUMB
#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)

View File

@ -7,6 +7,7 @@
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
@ -44,9 +45,9 @@ static void emit_pass1_load_id(emit_t *emit, qstr qstr) {
bool added;
id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added);
if (added) {
if (strcmp(qstr_str(qstr), "AssertionError") == 0) {
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
if (qstr == MP_QSTR_AssertionError) {
// TODO how much of a hack is this?
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
} else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) {
// special case, super is a global, and also counts as use of __class__
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;

View File

@ -113,11 +113,11 @@ DEF_RULE(import_stmt, nc, or(2), rule(import_name), rule(import_from))
DEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names))
DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3))
DEF_RULE(import_from_2, nc, or(2), rule(dotted_name), rule(import_from_2b))
DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipses), opt_rule(dotted_name))
DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))
DEF_RULE(import_from_3, nc, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))
DEF_RULE(import_as_names_paren, nc, and(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
DEF_RULE(one_or_more_period_or_ellipses, nc, one_or_more, rule(period_or_ellipses))
DEF_RULE(period_or_ellipses, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSES))
DEF_RULE(one_or_more_period_or_ellipsis, nc, one_or_more, rule(period_or_ellipsis))
DEF_RULE(period_or_ellipsis, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))
DEF_RULE(import_as_name, nc, and(2), tok(NAME), opt_rule(as_name))
DEF_RULE(dotted_as_name, nc, and(2), rule(dotted_name), opt_rule(as_name))
DEF_RULE(as_name, nc, and(2), tok(KW_AS), tok(NAME))
@ -220,7 +220,7 @@ DEF_RULE(power_dbl_star, c(power_dbl_star), and(2), tok(OP_DBL_STAR), rule(facto
// testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
DEF_RULE(atom, nc, or(10), tok(NAME), tok(NUMBER), rule(atom_string), tok(ELLIPSES), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
DEF_RULE(atom, nc, or(10), tok(NAME), tok(NUMBER), rule(atom_string), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
DEF_RULE(atom_string, c(atom_string), one_or_more, rule(string_or_bytes))
DEF_RULE(string_or_bytes, nc, or(2), tok(STRING), tok(BYTES))
DEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE))

View File

@ -239,7 +239,7 @@ static const uint8_t tok_enc_kind[] = {
MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSES,
MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSIS,
};
// must have the same order as enum in lexer.h

View File

@ -20,7 +20,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_STRING,
MP_TOKEN_BYTES,
MP_TOKEN_ELLIPSES,
MP_TOKEN_ELLIPSIS,
MP_TOKEN_KW_FALSE, // 12
MP_TOKEN_KW_NONE,

View File

@ -4,6 +4,20 @@
#include <mpconfigport.h>
#ifndef INT_FMT
// printf format spec to use for machine_int_t and friends
#ifdef __LP64__
// Archs where machine_int_t == long, long != int
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
#else
// Archs where machine_int_t == int
#define UINT_FMT "%u"
#define INT_FMT "%d"
#endif
#endif //INT_FMT
// Any options not explicitly set in mpconfigport.h will get default
// values below.
@ -11,3 +25,9 @@
#ifndef MICROPY_MEM_STATS
#define MICROPY_MEM_STATS (1)
#endif
// Whether to support slice object and correspondingly
// slice subscript operators
#ifndef MICROPY_ENABLE_SLICE
#define MICROPY_ENABLE_SLICE (1)
#endif

13
py/mpqstr.h Normal file
View File

@ -0,0 +1,13 @@
// See mpqstrraw.h for a list of qstr's that are available as constants.
// Reference them as MP_QSTR_xxxx.
//
// Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx")
// for qstrs that are referenced this way, but you don't want to have them in ROM.
enum {
MP_QSTR_nil = 0,
#define Q(id) MP_QSTR_##id,
#include "mpqstrraw.h"
#undef Q
MP_QSTR_number_of,
} category_t;

65
py/mpqstrraw.h Normal file
View File

@ -0,0 +1,65 @@
// All the qstr definitions in this file are available as constants.
// That is, they are in ROM and you can reference them simple as MP_QSTR_xxxx.
Q(__build_class__)
Q(__class__)
Q(__doc__)
Q(__init__)
Q(__locals__)
Q(__main__)
Q(__module__)
Q(__name__)
Q(__next__)
Q(__qualname__)
Q(__repl_print__)
Q(micropython)
Q(byte_code)
Q(native)
Q(viper)
Q(asm_thumb)
Q(Ellipsis)
Q(StopIteration)
Q(AssertionError)
Q(AttributeError)
Q(IndexError)
Q(KeyError)
Q(NameError)
Q(SyntaxError)
Q(TypeError)
Q(ValueError)
Q(abs)
Q(all)
Q(any)
Q(bool)
Q(callable)
Q(chr)
Q(complex)
Q(dict)
Q(divmod)
Q(float)
Q(hash)
Q(int)
Q(iter)
Q(len)
Q(list)
Q(max)
Q(min)
Q(next)
Q(ord)
Q(pow)
Q(print)
Q(range)
Q(set)
Q(sum)
Q(tuple)
Q(type)
Q(append)
Q(pop)
Q(sort)
Q(join)
Q(format)

View File

@ -5,9 +5,14 @@
.text
/* uint nlr_push(rdi=nlr_buf_t *nlr) */
#ifndef __apple_build_version__
.globl nlr_push
.type nlr_push, @function
nlr_push:
#else
.globl _nlr_push
_nlr_push:
#endif
movq (%rsp), %rax # load return %rip
movq %rax, 16(%rdi) # store %rip into nlr_buf
movq %rbp, 24(%rdi) # store %rbp into nlr_buf
@ -22,22 +27,36 @@ nlr_push:
movq %rdi, nlr_top(%rip) # stor new nlr_buf (to make linked list)
xorq %rax, %rax # return 0, normal return
ret # return
#ifndef __apple_build_version__
.size nlr_push, .-nlr_push
#endif
/* void nlr_pop() */
#ifndef __apple_build_version__
.globl nlr_pop
.type nlr_pop, @function
nlr_pop:
#else
.globl _nlr_pop
_nlr_pop:
#endif
movq nlr_top(%rip), %rax # get nlr_top into %rax
movq (%rax), %rax # load prev nlr_buf
movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list)
ret # return
#ifndef __apple_build_version__
.size nlr_pop, .-nlr_pop
#endif
/* void nlr_jump(rdi=uint val) */
#ifndef __apple_build_version__
.globl nlr_jump
.type nlr_jump, @function
nlr_jump:
#else
.globl _nlr_jump
_nlr_jump:
#endif
movq %rdi, %rax # put return value in %rax
movq nlr_top(%rip), %rdi # get nlr_top into %rdi
movq %rax, 8(%rdi) # store return value
@ -55,8 +74,12 @@ nlr_jump:
xorq %rax, %rax # clear return register
inc %al # increase to make 1, non-local return
ret # return
#ifndef __apple_build_version__
.size nlr_jump, .-nlr_jump
#endif
#ifndef __apple_build_version__
.local nlr_top
#endif
.comm nlr_top,8,8
#endif

View File

@ -7,15 +7,12 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
mp_obj_t mp_obj_new_int(machine_int_t value) {
return MP_OBJ_NEW_SMALL_INT(value);
}
const char *mp_obj_get_type_str(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
return "int";
@ -127,9 +124,13 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) {
return 1;
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
return MP_OBJ_SMALL_INT_VALUE(arg);
#if MICROPY_ENABLE_FLOAT
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
// TODO work out if this should be floor, ceil or trunc
return (machine_int_t)mp_obj_float_get(arg);
#endif
} else {
assert(0);
return 0;
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
}
}
@ -144,7 +145,7 @@ machine_float_t mp_obj_get_float(mp_obj_t arg) {
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
return mp_obj_float_get(arg);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
}
}
@ -164,7 +165,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
} else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
mp_obj_complex_get(arg, real, imag);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
}
}
#endif
@ -188,11 +189,11 @@ mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
mp_obj_list_get(o_in, &seq_len, &seq_items);
}
if (seq_len != n) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len));
}
return seq_items;
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
}
}
@ -204,10 +205,10 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
i += len;
}
if (i < 0 || i >= len) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_IndexError, "%s index out of range", type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_IndexError, "%s index out of range", type->name));
}
return i;
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
}
}

View File

@ -58,6 +58,7 @@ typedef mp_obj_t (*mp_fun_t)(void);
typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *);
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o);
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, int n_args, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
@ -71,6 +72,7 @@ struct _mp_obj_type_t {
mp_obj_base_t base;
const char *name;
mp_print_fun_t print;
mp_make_new_fun_t make_new; // to make an instance of the type
mp_call_n_fun_t call_n;
mp_unary_op_fun_t unary_op; // can return NULL if op not supported
@ -110,6 +112,8 @@ extern const mp_obj_type_t mp_const_type;
extern const mp_obj_t mp_const_none;
extern const mp_obj_t mp_const_false;
extern const mp_obj_t mp_const_true;
extern const mp_obj_t mp_const_empty_tuple;
extern const mp_obj_t mp_const_ellipsis;
extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
// Need to declare this here so we are not dependent on map.h
@ -144,6 +148,7 @@ mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(int n_args);
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth);
mp_obj_t mp_obj_new_class(struct _mp_map_t *class_locals);
mp_obj_t mp_obj_new_instance(mp_obj_t clas);
@ -178,6 +183,9 @@ extern const mp_obj_type_t bool_type;
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
// int
extern const mp_obj_type_t int_type;
// exception
extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in);
@ -212,8 +220,13 @@ uint mp_obj_dict_len(mp_obj_t self_in);
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
// set
extern const mp_obj_type_t set_type;
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
// slice
extern const mp_obj_type_t slice_type;
void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step);
// functions
typedef struct _mp_obj_fun_native_t { // need this so we can define const objects (to go in ROM)
mp_obj_base_t base;

View File

@ -4,14 +4,16 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
typedef struct _mp_obj_bool_t {
mp_obj_base_t base;
bool value;
} mp_obj_bool_t;
void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_bool_t *self = self_in;
if (self->value) {
print(env, "True");
@ -20,10 +22,20 @@ void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_ob
}
}
// args are reverse in the array
static mp_obj_t bool_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bool takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
}
}
const mp_obj_type_t bool_type = {
{ &mp_const_type },
"bool",
bool_print, // print
bool_make_new, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -37,6 +37,7 @@ const mp_obj_type_t bound_meth_type = {
{ &mp_const_type },
"bound_method",
NULL, // print
NULL, // make_new
bound_meth_call_n, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -27,6 +27,7 @@ const mp_obj_type_t cell_type = {
{ &mp_const_type },
"cell",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
@ -25,7 +26,7 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t o = mp_obj_new_instance(self_in);
// look for __init__ function
mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, qstr_from_str_static("__init__"), false);
mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, MP_QSTR___init__, false);
if (init_fn != NULL) {
// call __init__ function
@ -40,13 +41,13 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
m_del(mp_obj_t, args2, n_args + 1);
}
if (init_ret != mp_const_none) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
}
} else {
// TODO
if (n_args != 0) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args));
}
}
@ -63,6 +64,7 @@ const mp_obj_type_t class_type = {
{ &mp_const_type },
"class",
NULL, // print
NULL, // make_new
class_call_n, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -36,6 +36,7 @@ const mp_obj_type_t closure_type = {
{ &mp_const_type },
"closure",
NULL, // print
NULL, // make_new
closure_call_n, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "map.h"
@ -29,7 +30,46 @@ void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp
}
}
mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
// args are reverse in the array
static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
return mp_obj_new_complex(0, 0);
case 1:
// TODO allow string as first arg and parse it
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
return args[0];
} else {
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
}
case 2:
{
mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
mp_obj_get_complex(args[1], &real, &imag);
} else {
real = mp_obj_get_float(args[1]);
imag = 0;
}
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
mp_float_t real2, imag2;
mp_obj_get_complex(args[0], &real2, &imag2);
real -= imag2;
imag += real2;
} else {
imag += mp_obj_get_float(args[0]);
}
return mp_obj_new_complex(real, imag);
}
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "complex takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args));
}
}
static mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
mp_obj_complex_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->real != 0 || o->imag != 0) { return mp_const_true;} else { return mp_const_false; }
@ -39,7 +79,7 @@ mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
}
}
mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
static mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
mp_obj_complex_get(lhs_in, &lhs_real, &lhs_imag);
mp_obj_complex_get(rhs_in, &rhs_real, &rhs_imag);
@ -79,6 +119,7 @@ const mp_obj_type_t complex_type = {
{ &mp_const_type },
"complex",
complex_print, // print
complex_make_new, // make_new
NULL, // call_n
complex_unary_op, // unary_op
complex_binary_op, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -16,7 +17,7 @@ typedef struct _mp_obj_dict_t {
mp_map_t map;
} mp_obj_dict_t;
void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
bool first = true;
print(env, "{");
@ -34,7 +35,13 @@ void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_ob
print(env, "}");
}
mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// args are reverse in the array
static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
// TODO create from an iterable!
return rt_build_map(0);
}
static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = lhs_in;
switch (op) {
case RT_BINARY_OP_SUBSCR:
@ -42,7 +49,7 @@ mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// dict load
mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_KeyError, "<value>"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
} else {
return elem->value;
}
@ -57,6 +64,7 @@ const mp_obj_type_t dict_type = {
{ &mp_const_type },
"dict",
dict_print, // print
dict_make_new, // make_new
NULL, // call_n
NULL, // unary_op
dict_binary_op, // binary_op

View File

@ -39,6 +39,7 @@ const mp_obj_type_t exception_type = {
{ &mp_const_type },
"exception",
exception_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
@ -18,12 +19,30 @@ typedef struct _mp_obj_float_t {
mp_obj_t mp_obj_new_float(mp_float_t value);
void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
static void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
print(env, "%.8g", o->value);
}
mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
static mp_obj_t float_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
return mp_obj_new_float(0);
case 1:
// TODO allow string as arg and parse it
if (MP_OBJ_IS_TYPE(args[0], &float_type)) {
return args[0];
} else {
return mp_obj_new_float(mp_obj_get_float(args[0]));
}
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "float takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
}
}
static mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->value != 0) { return mp_const_true;} else { return mp_const_false; }
@ -33,7 +52,7 @@ mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
}
}
mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
static mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) {
return complex_type.binary_op(op, lhs_in, rhs_in);
}
@ -61,6 +80,7 @@ const mp_obj_type_t float_type = {
{ &mp_const_type },
"float",
float_print,
float_make_new, // make_new
NULL, // call_n
float_unary_op,
float_binary_op,

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "map.h"
#include "runtime.h"
@ -24,7 +25,7 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
// check number of arguments
if (n_args != self->n_args_min) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args));
}
// dispatch function call
@ -47,9 +48,9 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
// function takes a variable number of arguments
if (n_args < self->n_args_min) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args)));
} else if (n_args > self->n_args_max) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args));
}
// TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args
@ -69,6 +70,7 @@ const mp_obj_type_t fun_native_type = {
{ &mp_const_type },
"function",
NULL, // print
NULL, // make_new
fun_native_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@ -141,7 +143,7 @@ mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_bc_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
// optimisation: allow the compiler to optimise this tail call for
@ -161,6 +163,7 @@ const mp_obj_type_t fun_bc_type = {
{ &mp_const_type },
"function",
NULL, // print
NULL, // make_new
fun_bc_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@ -250,7 +253,7 @@ mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_asm_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
machine_uint_t ret;
@ -274,6 +277,7 @@ static const mp_obj_type_t fun_asm_type = {
{ &mp_const_type },
"function",
NULL, // print
NULL, // make_new
fun_asm_call_n, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "bc.h"
@ -29,7 +30,7 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
const byte *bc_code;
mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code);
if (n_args != bc_n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
}
return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args);
@ -39,6 +40,7 @@ const mp_obj_type_t gen_wrap_type = {
{ &mp_const_type },
"generator",
NULL, // print
NULL, // make_new
gen_wrap_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
@ -93,6 +95,7 @@ const mp_obj_type_t gen_instance_type = {
{ &mp_const_type },
"generator",
gen_instance_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
@ -44,7 +45,7 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) {
return elem->value;
}
}
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr)));
}
void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
@ -92,6 +93,7 @@ const mp_obj_type_t instance_type = {
{ &mp_const_type },
"instance",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

48
py/objint.c Normal file
View File

@ -0,0 +1,48 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
typedef struct _mp_obj_int_t {
mp_obj_base_t base;
} mp_obj_int_t;
static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
return MP_OBJ_NEW_SMALL_INT(0);
case 1:
// TODO allow string as arg and parse it
return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0]));
//case 2:
// TODO, parse with given base
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args));
}
}
const mp_obj_type_t int_type = {
{ &mp_const_type },
"int",
NULL,
int_make_new, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ { NULL, NULL }, }, // method list
};
mp_obj_t mp_obj_new_int(machine_int_t value) {
return MP_OBJ_NEW_SMALL_INT(value);
}

View File

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -35,6 +36,29 @@ static void list_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "]");
}
static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
// return a new, empty list
return rt_build_list(0, NULL);
case 1:
{
// make list from iterable
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t list = rt_build_list(0, NULL);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
rt_list_append(list, item);
}
return list;
}
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "list takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
}
}
static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_list_t *o = lhs;
switch (op) {
@ -81,7 +105,7 @@ static mp_obj_t list_pop(int n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(args[0], &list_type));
mp_obj_list_t *self = args[0];
if (self->len == 0) {
nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "pop from empty list"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "pop from empty list"));
}
uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1]);
mp_obj_t ret = self->items[index];
@ -185,6 +209,7 @@ const mp_obj_type_t list_type = {
{ &mp_const_type },
"list",
list_print, // print
list_make_new, // make_new
NULL, // call_n
NULL, // unary_op
list_binary_op, // binary_op
@ -263,6 +288,7 @@ static const mp_obj_type_t list_it_type = {
{ &mp_const_type },
"list_iterator",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -25,6 +25,7 @@ const mp_obj_type_t module_type = {
{ &mp_const_type },
"module",
module_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -18,6 +18,7 @@ const mp_obj_type_t none_type = {
{ &mp_const_type },
"NoneType",
none_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -26,6 +26,7 @@ static const mp_obj_type_t range_type = {
{ &mp_const_type} ,
"range",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
@ -70,6 +71,7 @@ static const mp_obj_type_t range_it_type = {
{ &mp_const_type },
"range_iterator",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -5,7 +5,9 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_set_t {
@ -29,10 +31,34 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
print(env, "}");
}
static const mp_obj_type_t set_type = {
static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
// return a new, empty set
return mp_obj_new_set(0, NULL);
case 1:
{
// 1 argument, an iterable from which we make a new set
mp_obj_t set = mp_obj_new_set(0, NULL);
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
mp_obj_set_store(set, item);
}
return set;
}
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "set takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
}
}
const mp_obj_type_t set_type = {
{ &mp_const_type },
"set",
set_print, // print
set_make_new, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

105
py/objslice.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
/******************************************************************************/
/* ellipsis object, a singleton */
typedef struct _mp_obj_ellipsis_t {
mp_obj_base_t base;
} mp_obj_ellipsis_t;
void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "Ellipsis");
}
const mp_obj_type_t ellipsis_type = {
{ &mp_const_type },
"ellipsis",
ellipsis_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
static const mp_obj_ellipsis_t ellipsis_obj = {{&ellipsis_type}};
const mp_obj_t mp_const_ellipsis = (mp_obj_t)&ellipsis_obj;
/******************************************************************************/
/* slice object */
#if MICROPY_ENABLE_SLICE
// TODO: This implements only variant of slice with 2 integer args only.
// CPython supports 3rd arg (step), plus args can be arbitrary Python objects.
typedef struct _mp_obj_slice_t {
mp_obj_base_t base;
machine_int_t start;
machine_int_t stop;
} mp_obj_slice_t;
void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_slice_t *o = o_in;
print(env, "slice(" INT_FMT ", " INT_FMT ")", o->start, o->stop);
}
const mp_obj_type_t slice_type = {
{ &mp_const_type },
"slice",
slice_print,
NULL, // call_n
NULL, // make_new
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ { NULL, NULL }, }, // method list
};
// TODO: Make sure to handle "empty" values, which are signified by None in CPython
mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
assert(ostep == NULL);
machine_int_t start = 0, stop = 0;
if (ostart != mp_const_none) {
start = mp_obj_get_int(ostart);
}
if (ostop != mp_const_none) {
stop = mp_obj_get_int(ostop);
if (stop == 0) {
// [x:0] is a special case - in our slice object, stop = 0 means
// "end of sequence". Fortunately, [x:0] is an empty seqence for
// any x (including negative). [x:x] is also always empty sequence.
// but x also can be 0. But note that b""[x:x] is b"" for any x (i.e.
// no IndexError, at least in Python 3.3.3). So, we just use -1's to
// signify that. -1 is catchy "special" number in case someone will
// try to print [x:0] slice ever.
start = stop = -1;
}
}
mp_obj_slice_t *o = m_new(mp_obj_slice_t, 1);
o->base.type = &slice_type;
o->start = start;
o->stop = stop;
return (mp_obj_t)o;
}
void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step) {
assert(MP_OBJ_IS_TYPE(self_in, &slice_type));
mp_obj_slice_t *self = self_in;
*start = self->start;
*stop = self->stop;
*step = 1;
}
#endif

View File

@ -7,6 +7,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -27,9 +28,42 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
const char *lhs_str = qstr_str(lhs->qstr);
switch (op) {
case RT_BINARY_OP_SUBSCR:
// string access
// XXX a massive hack!
return mp_obj_new_int(lhs_str[mp_obj_get_int(rhs_in)]);
// TODO: need predicate to check for int-like type (bools are such for example)
// ["no", "yes"][1 == 2] is common idiom
if (MP_OBJ_IS_SMALL_INT(rhs_in)) {
// TODO: This implements byte string access for single index so far
// TODO: Handle negative indexes.
return mp_obj_new_int(lhs_str[mp_obj_get_int(rhs_in)]);
#if MICROPY_ENABLE_SLICE
} else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) {
machine_int_t start, stop, step;
mp_obj_slice_get(rhs_in, &start, &stop, &step);
assert(step == 1);
int len = strlen(lhs_str);
if (start < 0) {
start = len + start;
if (start < 0) {
start = 0;
}
} else if (start > len) {
start = len;
}
if (stop <= 0) {
stop = len + stop;
// CPython returns empty string in such case
if (stop < 0) {
stop = start;
}
} else if (stop > len) {
stop = len;
}
return mp_obj_new_str(qstr_from_strn_copy(lhs_str + start, stop - start));
#endif
} else {
// Message doesn't match CPython, but we don't have so much bytes as they
// to spend them on verbose wording
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int"));
}
case RT_BINARY_OP_ADD:
case RT_BINARY_OP_INPLACE_ADD:
@ -101,7 +135,7 @@ mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
return mp_obj_new_str(qstr_from_str_take(joined_str, required_len + 1));
bad_arg:
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's"));
}
void vstr_printf_wrapper(void *env, const char *fmt, ...) {
@ -125,7 +159,7 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) {
vstr_add_char(vstr, '{');
} else if (*str == '}') {
if (arg_i >= n_args) {
nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "tuple index out of range"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range"));
}
mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
arg_i++;
@ -145,6 +179,7 @@ const mp_obj_type_t str_type = {
{ &mp_const_type },
"str",
str_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
str_binary_op, // binary_op

View File

@ -1,13 +1,14 @@
#include <stdlib.h>
#include <stdint.h>
//#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
typedef struct _mp_obj_tuple_t {
mp_obj_base_t base;
@ -20,7 +21,7 @@ static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur);
/******************************************************************************/
/* tuple */
void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
static void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_tuple_t *o = o_in;
print(env, "(");
for (int i = 0; i < o->len; i++) {
@ -35,7 +36,48 @@ void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_o
print(env, ")");
}
mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
// args are in reverse order in the array
static mp_obj_t tuple_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
// return a empty tuple
return mp_const_empty_tuple;
case 1:
{
// 1 argument, an iterable from which we make a new tuple
if (MP_OBJ_IS_TYPE(args[0], &tuple_type)) {
return args[0];
}
// TODO optimise for cases where we know the length of the iterator
uint alloc = 4;
uint len = 0;
mp_obj_t *items = m_new(mp_obj_t, alloc);
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (len >= alloc) {
items = m_renew(mp_obj_t, items, alloc, alloc * 2);
alloc *= 2;
}
items[len++] = item;
}
mp_obj_t tuple = mp_obj_new_tuple(len, items);
m_free(items, alloc);
return tuple;
}
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "tuple takes at most 1 argument, %d given", (void*)(machine_int_t)n_args));
}
}
static mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = lhs;
switch (op) {
case RT_BINARY_OP_SUBSCR:
@ -50,20 +92,15 @@ mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
}
mp_obj_t tuple_getiter(mp_obj_t o_in) {
static mp_obj_t tuple_getiter(mp_obj_t o_in) {
return mp_obj_new_tuple_iterator(o_in, 0);
}
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
mp_obj_tuple_t *self = self_in;
*len = self->len;
*items = &self->items[0];
}
const mp_obj_type_t tuple_type = {
{ &mp_const_type },
"tuple",
tuple_print, // print
tuple_make_new, // make_new
NULL, // call_n
NULL, // unary_op
tuple_binary_op, // binary_op
@ -72,7 +109,14 @@ const mp_obj_type_t tuple_type = {
{{NULL, NULL},}, // method list
};
// the zero-length tuple
static const mp_obj_tuple_t empty_tuple_obj = {{&tuple_type}, 0};
const mp_obj_t mp_const_empty_tuple = (mp_obj_t)&empty_tuple_obj;
mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) {
if (n == 0) {
return mp_const_empty_tuple;
}
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
@ -83,6 +127,9 @@ mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) {
}
mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) {
if (n == 0) {
return mp_const_empty_tuple;
}
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
@ -92,6 +139,12 @@ mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) {
return o;
}
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
mp_obj_tuple_t *self = self_in;
*len = self->len;
*items = &self->items[0];
}
/******************************************************************************/
/* tuple iterator */
@ -101,7 +154,7 @@ typedef struct _mp_obj_tuple_it_t {
machine_uint_t cur;
} mp_obj_tuple_it_t;
mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
static mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_it_t *self = self_in;
if (self->cur < self->tuple->len) {
mp_obj_t o_out = self->tuple->items[self->cur];
@ -116,6 +169,7 @@ static const mp_obj_type_t tuple_it_type = {
{ &mp_const_type },
"tuple_iterator",
NULL, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -4,17 +4,30 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "<a type>");
static void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_type_t *self = self_in;
print(env, "<class '%s'>", self->name);
}
static mp_obj_t type_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_type_t *self = self_in;
if (self->make_new != NULL) {
// TODO we need to init the object if it's an instance of a type
return self->make_new(self, n_args, args);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "cannot create '%s' instances", self->name));
}
}
const mp_obj_type_t mp_const_type = {
{ &mp_const_type },
"<a type>",
"type",
type_print, // print
NULL, // call_n
NULL, // make_new
type_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter

101
py/qstr.c
View File

@ -2,55 +2,110 @@
#include <string.h>
#include "misc.h"
#include "mpqstr.h"
static int qstrs_alloc;
static int qstrs_len;
static const char **qstrs;
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
// ultimately we will replace this with a static hash table of some kind
// also probably need to include the length in the string data, to allow null bytes in the string
#if 0 // print debugging info
#include <stdio.h>
#define DEBUG_printf(args...) printf(args)
#else // don't print debugging info
#define DEBUG_printf(args...) (void)0
#endif
typedef struct _qstr_pool_t {
struct _qstr_pool_t *prev;
uint total_prev_len;
uint alloc;
uint len;
const char *qstrs[];
} qstr_pool_t;
const static qstr_pool_t const_pool = {
NULL, // no previous pool
0, // no previous pool
10, // set so that the first dynamically allocated pool is twice this size; must be <= the len (just below)
MP_QSTR_number_of, // corresponds to number of strings in array just below
{
"nil", // must be first, since 0 qstr is nil
#define Q(id) #id,
#include "mpqstrraw.h"
#undef Q
},
};
static qstr_pool_t *last_pool = (qstr_pool_t*)&const_pool; // we won't modify the const_pool since it has no allocated room left
void qstr_init(void) {
qstrs_alloc = 400;
qstrs_len = 1;
qstrs = m_new(const char*, qstrs_alloc);
qstrs[0] = "nil";
// nothing to do!
}
static qstr qstr_add(const char *str) {
if (qstrs_len >= qstrs_alloc) {
qstrs = m_renew(const char*, qstrs, qstrs_alloc, qstrs_alloc * 2);
qstrs_alloc *= 2;
DEBUG_printf("QSTR: add %s\n", str);
// make sure we have room in the pool for a new qstr
if (last_pool->len >= last_pool->alloc) {
qstr_pool_t *pool = m_new_obj_var(qstr_pool_t, const char*, last_pool->alloc * 2);
pool->prev = last_pool;
pool->total_prev_len = last_pool->total_prev_len + last_pool->len;
pool->alloc = last_pool->alloc * 2;
pool->len = 0;
last_pool = pool;
DEBUG_printf("QSTR: allocate new pool of size %d\n", last_pool->alloc);
}
qstrs[qstrs_len++] = str;
return qstrs_len - 1;
// add the new qstr
last_pool->qstrs[last_pool->len++] = str;
// return id for the newly-added qstr
return last_pool->total_prev_len + last_pool->len - 1;
}
qstr qstr_from_str_static(const char *str) {
for (int i = 0; i < qstrs_len; i++) {
if (strcmp(qstrs[i], str) == 0) {
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strcmp(*qstr, str) == 0) {
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(str);
}
qstr qstr_from_str_take(char *str, int alloc_len) {
for (int i = 0; i < qstrs_len; i++) {
if (strcmp(qstrs[i], str) == 0) {
m_del(char, str, alloc_len);
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strcmp(*qstr, str) == 0) {
m_del(char, str, alloc_len);
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(str);
}
qstr qstr_from_strn_copy(const char *str, int len) {
for (int i = 0; i < qstrs_len; i++) {
if (strncmp(qstrs[i], str, len) == 0 && qstrs[i][len] == '\0') {
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strncmp(*qstr, str, len) == 0 && (*qstr)[len] == '\0') {
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(strndup(str, len));
}
// convert qstr id to pointer to its string
const char *qstr_str(qstr qstr) {
return qstrs[qstr];
// search
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
if (qstr >= pool->total_prev_len) {
return pool->qstrs[qstr - pool->total_prev_len];
}
}
// not found, return nil
return const_pool.qstrs[0];
}

View File

@ -11,6 +11,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -27,22 +28,6 @@
#define DEBUG_OP_printf(args...) (void)0
#endif
// TODO make these predefined so they don't take up RAM
qstr rt_q_append;
qstr rt_q_pop;
qstr rt_q_sort;
qstr rt_q_join;
qstr rt_q_format;
qstr rt_q___build_class__;
qstr rt_q___next__;
qstr rt_q_AttributeError;
qstr rt_q_IndexError;
qstr rt_q_KeyError;
qstr rt_q_NameError;
qstr rt_q_TypeError;
qstr rt_q_SyntaxError;
qstr rt_q_ValueError;
// locals and globals need to be pointers because they can be the same in outer module scope
static mp_map_t *map_locals;
static mp_map_t *map_globals;
@ -83,74 +68,64 @@ FILE *fp_write_code = NULL;
#endif
void rt_init(void) {
rt_q_append = qstr_from_str_static("append");
rt_q_pop = qstr_from_str_static("pop");
rt_q_sort = qstr_from_str_static("sort");
rt_q_join = qstr_from_str_static("join");
rt_q_format = qstr_from_str_static("format");
rt_q___build_class__ = qstr_from_str_static("__build_class__");
rt_q___next__ = qstr_from_str_static("__next__");
rt_q_AttributeError = qstr_from_str_static("AttributeError");
rt_q_IndexError = qstr_from_str_static("IndexError");
rt_q_KeyError = qstr_from_str_static("KeyError");
rt_q_NameError = qstr_from_str_static("NameError");
rt_q_TypeError = qstr_from_str_static("TypeError");
rt_q_SyntaxError = qstr_from_str_static("SyntaxError");
rt_q_ValueError = qstr_from_str_static("ValueError");
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
map_locals = map_globals = mp_map_new(MP_MAP_QSTR, 1);
mp_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = mp_obj_new_str(qstr_from_str_static("__main__"));
mp_qstr_map_lookup(map_globals, MP_QSTR___name__, true)->value = mp_obj_new_str(MP_QSTR___main__);
// init built-in hash table
mp_map_init(&map_builtins, MP_MAP_QSTR, 3);
// built-in exceptions (TODO, make these proper classes)
mp_qstr_map_lookup(&map_builtins, rt_q_AttributeError, true)->value = mp_obj_new_exception(rt_q_AttributeError);
mp_qstr_map_lookup(&map_builtins, rt_q_IndexError, true)->value = mp_obj_new_exception(rt_q_IndexError);
mp_qstr_map_lookup(&map_builtins, rt_q_KeyError, true)->value = mp_obj_new_exception(rt_q_KeyError);
mp_qstr_map_lookup(&map_builtins, rt_q_NameError, true)->value = mp_obj_new_exception(rt_q_NameError);
mp_qstr_map_lookup(&map_builtins, rt_q_TypeError, true)->value = mp_obj_new_exception(rt_q_TypeError);
mp_qstr_map_lookup(&map_builtins, rt_q_SyntaxError, true)->value = mp_obj_new_exception(rt_q_SyntaxError);
mp_qstr_map_lookup(&map_builtins, rt_q_ValueError, true)->value = mp_obj_new_exception(rt_q_ValueError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_AttributeError, true)->value = mp_obj_new_exception(MP_QSTR_AttributeError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_IndexError, true)->value = mp_obj_new_exception(MP_QSTR_IndexError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_KeyError, true)->value = mp_obj_new_exception(MP_QSTR_KeyError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_NameError, true)->value = mp_obj_new_exception(MP_QSTR_NameError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_TypeError, true)->value = mp_obj_new_exception(MP_QSTR_TypeError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_SyntaxError, true)->value = mp_obj_new_exception(MP_QSTR_SyntaxError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ValueError, true)->value = mp_obj_new_exception(MP_QSTR_ValueError);
// built-in objects
mp_qstr_map_lookup(&map_builtins, MP_QSTR_Ellipsis, true)->value = mp_const_ellipsis;
// built-in core functions
mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(mp_builtin___repl_print__);
mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__);
mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__);
// built-in user functions
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(mp_builtin_abs);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(mp_builtin_all);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(mp_builtin_any);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, mp_builtin_bool);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(mp_builtin_callable);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(mp_builtin_chr);
// built-in types
mp_qstr_map_lookup(&map_builtins, MP_QSTR_bool, true)->value = (mp_obj_t)&bool_type;
#if MICROPY_ENABLE_FLOAT
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = (mp_obj_t)&mp_builtin_complex_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_complex, true)->value = (mp_obj_t)&complex_type;
#endif
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(mp_builtin_dict);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(mp_builtin_divmod);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_dict, true)->value = (mp_obj_t)&dict_type;
#if MICROPY_ENABLE_FLOAT
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("float"), true)->value = (mp_obj_t)&mp_builtin_float_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_float, true)->value = (mp_obj_t)&float_type;
#endif
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = (mp_obj_t)&mp_builtin_hash_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("int"), true)->value = (mp_obj_t)&mp_builtin_int_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = (mp_obj_t)&mp_builtin_iter_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(mp_builtin_len);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, mp_builtin_list);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, mp_builtin_max);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, mp_builtin_min);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = (mp_obj_t)&mp_builtin_next_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(mp_builtin_ord);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, mp_builtin_pow);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, mp_builtin_print);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, mp_builtin_range);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("set"), true)->value = (mp_obj_t)&mp_builtin_set_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, mp_builtin_sum);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("type"), true)->value = (mp_obj_t)&mp_builtin_type_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_int, true)->value = (mp_obj_t)&int_type;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = (mp_obj_t)&list_type;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&set_type;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_tuple, true)->value = (mp_obj_t)&tuple_type;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj; // TODO
// built-in user functions; TODO covert all to &mp_builtin_xxx's
mp_qstr_map_lookup(&map_builtins, MP_QSTR_abs, true)->value = rt_make_function_1(mp_builtin_abs);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_all, true)->value = rt_make_function_1(mp_builtin_all);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_any, true)->value = rt_make_function_1(mp_builtin_any);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_callable, true)->value = rt_make_function_1(mp_builtin_callable);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_chr, true)->value = rt_make_function_1(mp_builtin_chr);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_hash, true)->value = (mp_obj_t)&mp_builtin_hash_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_iter, true)->value = (mp_obj_t)&mp_builtin_iter_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_len, true)->value = rt_make_function_1(mp_builtin_len);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_max, true)->value = rt_make_function_var(1, mp_builtin_max);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_min, true)->value = rt_make_function_var(1, mp_builtin_min);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_next, true)->value = (mp_obj_t)&mp_builtin_next_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ord, true)->value = rt_make_function_1(mp_builtin_ord);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_pow, true)->value = rt_make_function_var(2, mp_builtin_pow);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_print, true)->value = rt_make_function_var(0, mp_builtin_print);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_range, true)->value = rt_make_function_var(1, mp_builtin_range);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_sum, true)->value = rt_make_function_var(1, mp_builtin_sum);
next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
next_unique_code_id = 1; // 0 indicates "no code"
unique_codes = NULL;
#ifdef WRITE_CODE
@ -166,12 +141,8 @@ void rt_deinit(void) {
#endif
}
int rt_get_unique_code_id(bool is_main_module) {
if (is_main_module) {
return 1;
} else {
return next_unique_code_id++;
}
int rt_get_unique_code_id(void) {
return next_unique_code_id++;
}
static void alloc_unique_codes(void) {
@ -186,7 +157,7 @@ static void alloc_unique_codes(void) {
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator) {
alloc_unique_codes();
assert(unique_code_id < next_unique_code_id);
assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
unique_codes[unique_code_id].kind = MP_CODE_BYTE;
unique_codes[unique_code_id].n_args = n_args;
unique_codes[unique_code_id].n_locals = n_locals;
@ -355,7 +326,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
}
}
if (*s != 0) {
nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "invalid syntax for number"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "invalid syntax for number"));
}
if (exp_neg) {
exp_val = -exp_val;
@ -373,7 +344,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
return mp_obj_new_float(dec_val);
}
#else
nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "decimal numbers not supported"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "decimal numbers not supported"));
#endif
}
@ -391,7 +362,7 @@ mp_obj_t rt_load_name(qstr qstr) {
if (elem == NULL) {
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
}
}
@ -405,7 +376,7 @@ mp_obj_t rt_load_global(qstr qstr) {
if (elem == NULL) {
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
}
return elem->value;
@ -413,9 +384,9 @@ mp_obj_t rt_load_global(qstr qstr) {
mp_obj_t rt_load_build_class(void) {
DEBUG_OP_printf("load_build_class\n");
mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, false);
mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_NameError, "name '__build_class__' is not defined"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_NameError, "name '__build_class__' is not defined"));
}
return elem->value;
}
@ -465,7 +436,7 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
}
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bad operand type for unary operator: '%s'", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", o->type->name));
}
}
@ -544,7 +515,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs)));
}
mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
@ -693,13 +664,13 @@ mp_obj_t rt_call_function_n(mp_obj_t fun_in, int n_args, const mp_obj_t *args) {
DEBUG_OP_printf("calling function %p(n_args=%d, args=%p)\n", fun_in, n_args, args);
if (MP_OBJ_IS_SMALL_INT(fun_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not callable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not callable"));
} else {
mp_obj_base_t *fun = fun_in;
if (fun->type->call_n != NULL) {
return fun->type->call_n(fun_in, n_args, args);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not callable", fun->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name));
}
}
}
@ -756,14 +727,14 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
mp_obj_list_get(seq_in, &seq_len, &seq_items);
}
if (seq_len < num) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len));
} else if (seq_len > num) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num));
}
memcpy(items, seq_items, num * sizeof(mp_obj_t));
} else {
// TODO call rt_getiter and extract via rt_iternext
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in)));
}
}
@ -807,12 +778,12 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
}
no_attr:
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
DEBUG_OP_printf("load method %s\n", qstr_str(attr));
if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == rt_q___next__) {
if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == MP_QSTR___next__) {
dest[1] = (mp_obj_t)&mp_builtin_next_obj;
dest[0] = base;
return;
@ -850,7 +821,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
mp_map_t *globals = mp_obj_module_get_globals(base);
mp_qstr_map_lookup(globals, attr, true)->value = value;
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
}
@ -869,26 +840,26 @@ void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
mp_obj_t rt_getiter(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not iterable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not iterable"));
} else {
mp_obj_base_t *o = o_in;
if (o->type->getiter != NULL) {
return o->type->getiter(o_in);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", o->type->name));
}
}
}
mp_obj_t rt_iternext(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "? 'int' object is not iterable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "? 'int' object is not iterable"));
} else {
mp_obj_base_t *o = o_in;
if (o->type->iternext != NULL) {
return o->type->iternext(o_in);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "? '%s' object is not iterable", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "? '%s' object is not iterable", o->type->name));
}
}
}

View File

@ -1,18 +1,3 @@
extern qstr rt_q_append;
extern qstr rt_q_pop;
extern qstr rt_q_sort;
extern qstr rt_q_join;
extern qstr rt_q_format;
extern qstr rt_q___build_class__;
extern qstr rt_q___next__;
extern qstr rt_q_AttributeError;
extern qstr rt_q_IndexError;
extern qstr rt_q_KeyError;
extern qstr rt_q_NameError;
extern qstr rt_q_TypeError;
extern qstr rt_q_SyntaxError;
extern qstr rt_q_ValueError;
int rt_is_true(mp_obj_t arg);
mp_obj_t rt_load_const_dec(qstr qstr);

View File

@ -81,7 +81,7 @@ extern void *const rt_fun_table[RT_F_NUMBER_OF];
void rt_init(void);
void rt_deinit(void);
int rt_get_unique_code_id(bool is_main_module);
int rt_get_unique_code_id(void);
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator);
void rt_assign_native_code(int unique_code_id, void *f, uint len, int n_args);
void rt_assign_inline_asm_code(int unique_code_id, void *f, uint len, int n_args);

View File

@ -46,6 +46,10 @@ void mp_show_byte_code(const byte *ip, int len) {
printf("LOAD_CONST_TRUE");
break;
case MP_BC_LOAD_CONST_ELLIPSIS:
printf("LOAD_CONST_ELLIPSIS");
break;
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;

18
py/vm.c
View File

@ -99,6 +99,10 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
PUSH(mp_const_true);
break;
case MP_BC_LOAD_CONST_ELLIPSIS:
PUSH(mp_const_ellipsis);
break;
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;
@ -410,6 +414,20 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
sp++;
break;
#if MICROPY_ENABLE_SLICE
case MP_BC_BUILD_SLICE:
DECODE_UINT;
if (unum == 2) {
obj2 = POP();
obj1 = TOP();
SET_TOP(mp_obj_new_slice(obj1, obj2, NULL));
} else {
printf("3-argument slice is not supported\n");
assert(0);
}
break;
#endif
case MP_BC_UNPACK_SEQUENCE:
DECODE_UINT;
rt_unpack_sequence(sp[0], unum, sp - unum + 1);

View File

@ -73,11 +73,13 @@ PY_O = \
objfun.o \
objgenerator.o \
objinstance.o \
objint.o \
objlist.o \
objmodule.o \
objnone.o \
objrange.o \
objset.o \
objslice.o \
objstr.o \
objtuple.o \
objtype.o \
@ -161,7 +163,7 @@ $(BUILD)/flash.elf: $(OBJ)
arm-none-eabi-size $@
$(BUILD):
mkdir $@
mkdir -p $@
$(BUILD)/%.o: %.s
$(AS) -o $@ $<

View File

@ -330,6 +330,7 @@ static const mp_obj_type_t i2c_obj_type = {
{ &mp_const_type },
"I2C",
i2c_obj_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -108,6 +108,7 @@ static const mp_obj_type_t led_obj_type = {
{ &mp_const_type },
"Led",
led_obj_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -15,6 +15,7 @@
#include "misc.h"
#include "ff.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
@ -621,7 +622,7 @@ mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
}
pin_error:
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "pin %s does not exist", pin_name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
@ -745,6 +746,7 @@ static const mp_obj_type_t file_obj_type = {
{ &mp_const_type },
"File",
file_obj_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -141,6 +141,7 @@ static const mp_obj_type_t servo_obj_type = {
{ &mp_const_type },
"Servo",
servo_obj_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op

View File

@ -49,6 +49,18 @@ static uint8_t *cache_get_addr_for_write(uint32_t flash_addr) {
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
}
static uint8_t *cache_get_addr_for_read(uint32_t flash_addr) {
uint32_t flash_sector_start;
uint32_t flash_sector_size;
uint32_t flash_sector_id = flash_get_sector_info(flash_addr, &flash_sector_start, &flash_sector_size);
if (cache_flash_sector_id == flash_sector_id) {
// in cache, copy from there
return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start;
}
// not in cache, copy straight from flash
return (uint8_t*)flash_addr;
}
void storage_init(void) {
if (!is_initialised) {
cache_flash_sector_id = 0;
@ -131,8 +143,9 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
return true;
} else if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
// non-MBR block, just copy straight from flash
uint8_t *src = (uint8_t*)FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK) * BLOCK_SIZE;
// non-MBR block, get data from flash memory, possibly via cache
uint32_t flash_addr = FLASH_MEM_START_ADDR + (block - FLASH_PART1_START_BLOCK) * BLOCK_SIZE;
uint8_t *src = cache_get_addr_for_read(flash_addr);
memcpy(dest, src, BLOCK_SIZE);
return true;

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
RM="/bin/rm -f"
CPYTHON3=python3
CPYTHON3=python3.3
MP_PY=../../unix/py
numtests=0

View File

@ -0,0 +1,32 @@
print("123"[0:1])
print("123"[0:2])
print("123"[:1])
print("123"[1:])
# Idiom for copying sequence
print("123"[:])
print("123"[:-1])
# Weird cases
print("123"[0:0])
print("123"[1:0])
print("123"[1:1])
print("123"[-1:-1])
print("123"[-3:])
print("123"[-3:3])
print("123"[0:])
print("123"[:0])
print("123"[:-3])
print("123"[:-4])
# Range check testing, don't segfault, please ;-)
print("123"[:1000000])
print("123"[1000000:])
print("123"[:-1000000])
print("123"[-1000000:])
# No IndexError!
print(""[1:1])
print(""[-1:-1])

View File

@ -38,11 +38,13 @@ PY_O = \
objfun.o \
objgenerator.o \
objinstance.o \
objint.o \
objlist.o \
objmodule.o \
objnone.o \
objrange.o \
objset.o \
objslice.o \
objstr.o \
objtuple.o \
objtype.o \

View File

@ -11,15 +11,11 @@
#ifdef __LP64__
typedef long machine_int_t; // must be pointer size
typedef unsigned long machine_uint_t; // must be pointer size
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
#else
// These are definitions for machines where sizeof(int) == sizeof(void*),
// regardless for actual size.
typedef int machine_int_t; // must be pointer size
typedef unsigned int machine_uint_t; // must be pointer size
#define UINT_FMT "%u"
#define INT_FMT "%d"
#endif
#define BYTES_PER_WORD sizeof(machine_int_t)

View File

@ -2,7 +2,7 @@ PYSRC=../py
BUILD=build
CC = gcc
CFLAGS = -I. -I$(PYSRC) -Wall -Werror -ansi -std=gnu99 -Os -DUSE_READLINE #-DNDEBUG
CFLAGS = -I. -I$(PYSRC) -Wall -Werror -ansi -std=gnu99 -Os #-DNDEBUG
LDFLAGS = -lm
SRC_C = \
@ -45,11 +45,13 @@ PY_O = \
objfun.o \
objgenerator.o \
objinstance.o \
objint.o \
objlist.o \
objmodule.o \
objnone.o \
objrange.o \
objset.o \
objslice.o \
objstr.o \
objtuple.o \
objtype.o \
@ -82,10 +84,10 @@ $(BUILD)/%.o: $(PYSRC)/%.S
$(BUILD)/%.o: $(PYSRC)/%.c mpconfigport.h
$(CC) $(CFLAGS) -c -o $@ $<
$(BUILD)/emitnx64.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
$(BUILD)/emitnx64.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h mpconfigport.h
$(CC) $(CFLAGS) -DN_X64 -c -o $@ $<
$(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
$(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h mpconfigport.h
$(CC) $(CFLAGS) -DN_THUMB -c -o $@ $<
# optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster)

View File

@ -15,7 +15,7 @@
#include "runtime.h"
#include "repl.h"
#ifdef USE_READLINE
#if MICROPY_USE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
@ -35,7 +35,7 @@ static char *str_join(const char *s1, int sep_char, const char *s2) {
}
static char *prompt(char *p) {
#ifdef USE_READLINE
#if MICROPY_USE_READLINE
char *line = readline(p);
if (line) {
add_history(line);
@ -192,6 +192,7 @@ static const mp_obj_type_t test_type = {
{ &mp_const_type },
"Test",
test_print, // print
NULL, // make_new
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
@ -217,6 +218,13 @@ int main(int argc, char **argv) {
rt_store_name(qstr_from_str_static("test"), test_obj_new(42));
/*
printf("bytes:\n");
printf(" total %d\n", m_get_total_bytes_allocated());
printf(" cur %d\n", m_get_current_bytes_allocated());
printf(" peak %d\n", m_get_peak_bytes_allocated());
*/
if (argc == 1) {
do_repl();
} else if (argc == 2) {

View File

@ -1,5 +1,10 @@
// options to control how Micro Python is built
// Linking with GNU readline causes binary to be licensed under GPL
#ifndef MICROPY_USE_READLINE
#define MICROPY_USE_READLINE (1)
#endif
#define MICROPY_ENABLE_FLOAT (1)
#define MICROPY_EMIT_CPYTHON (0)
#define MICROPY_EMIT_X64 (1)
@ -11,15 +16,11 @@
#ifdef __LP64__
typedef long machine_int_t; // must be pointer size
typedef unsigned long machine_uint_t; // must be pointer size
#define UINT_FMT "%lu"
#define INT_FMT "%ld"
#else
// These are definitions for machines where sizeof(int) == sizeof(void*),
// regardless for actual size.
typedef int machine_int_t; // must be pointer size
typedef unsigned int machine_uint_t; // must be pointer size
#define UINT_FMT "%u"
#define INT_FMT "%d"
#endif
#define BYTES_PER_WORD sizeof(machine_int_t)