Commit 65dc960e authored by Damien George's avatar Damien George
Browse files

unix-cpy: Remove unix-cpy. It's no longer needed.

unix-cpy was originally written to get semantic equivalent with CPython
without writing functional tests.  When writing the initial
implementation of uPy it was a long way between lexer and functional
tests, so the half-way test was to make sure that the bytecode was
correct.  The idea was that if the uPy bytecode matched CPython 1-1 then
uPy would be proper Python if the bytecodes acted correctly.  And having
matching bytecode meant that it was less likely to miss some deep
subtlety in the Python semantics that would require an architectural
change later on.

But that is all history and it no longer makes sense to retain the
ability to output CPython bytecode, because:

1. It outputs CPython 3.3 compatible bytecode.  CPython's bytecode
changes from version to version, and seems to have changed quite a bit
in 3.5.  There's no point in changing the bytecode output to match
CPython anymore.

2. uPy and CPy do different optimisations to the bytecode which makes it
harder to match.

3. The bytecode tests are not run.  They were never part of Travis and
are not run locally anymore.

4. The EMIT_CPYTHON option needs a lot of extra source code which adds
heaps of noise, especially in compile.c.

5. Now that there is an extensive test suite (which tests functionality)
there is no need to match the bytecode.  Some very subtle behaviour is
tested with the test suite and passing these tests is a much better
way to stay Python-language compliant, rather than trying to match
CPy bytecode.
parent 0e978349
......@@ -16,7 +16,6 @@ before_script:
script:
- make -C minimal test
- make -C unix CC=gcc-4.7
- make -C unix-cpy CC=gcc-4.7
- make -C bare-arm
- make -C qemu-arm test
- make -C stmhal
......
......@@ -47,7 +47,6 @@ Additional components:
- pic16bit/ -- a version of Micro Python for 16-bit PIC microcontrollers.
- cc3200/ -- a version of Micro Python that runs on the CC3200 from TI.
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
- unix-cpy/ -- a version of Micro Python that outputs bytecode (for testing).
- tests/ -- test framework and test scripts.
- tools/ -- various tools, including the pyboard.py module.
- examples/ -- a few example Python scripts.
......
This diff is collapsed.
......@@ -145,14 +145,6 @@ typedef struct _emit_method_table_t {
// they may or may not emit code
void (*start_except_handler)(emit_t *emit);
void (*end_except_handler)(emit_t *emit);
#if MICROPY_EMIT_CPYTHON
// these methods are only needed for emitcpy
void (*load_const_verbatim_strn)(emit_t *emit, const char *str, mp_uint_t len);
void (*load_closure)(emit_t *emit, qstr qst, mp_uint_t local_num);
void (*setup_loop)(emit_t *emit, mp_uint_t label);
#endif
} emit_method_table_t;
void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst);
......
......@@ -34,8 +34,6 @@
#include "py/emit.h"
#include "py/bc0.h"
#if !MICROPY_EMIT_CPYTHON
#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
#define DUMMY_DATA_SIZE (BYTES_FOR_INT)
......@@ -1030,5 +1028,3 @@ const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_delete_id_ops = {
mp_emit_bc_delete_global,
};
#endif
#endif // !MICROPY_EMIT_CPYTHON
......@@ -33,28 +33,12 @@ void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
bool added;
id_info_t *id = scope_find_or_add_id(scope, qst, &added);
if (added) {
#if MICROPY_EMIT_CPYTHON
if (qst == MP_QSTR_super && scope->kind == SCOPE_FUNCTION) {
// special case, super is a global, and also counts as use of __class__
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
id_info_t *id2 = scope_find_local_in_parent(scope, MP_QSTR___class__);
if (id2 != NULL) {
id2 = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
if (added) {
id2->kind = ID_INFO_KIND_FREE;
scope_close_over_in_parents(scope, MP_QSTR___class__);
}
}
} else
#endif
{
id_info_t *id2 = scope_find_local_in_parent(scope, qst);
if (id2 != NULL && (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE)) {
id->kind = ID_INFO_KIND_FREE;
scope_close_over_in_parents(scope, qst);
} else {
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
}
id_info_t *id2 = scope_find_local_in_parent(scope, qst);
if (id2 != NULL && (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE)) {
id->kind = ID_INFO_KIND_FREE;
scope_close_over_in_parents(scope, qst);
} else {
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
}
}
}
......
This diff is collapsed.
......@@ -75,7 +75,7 @@ $(HEADER_BUILD):
$(MKDIR) -p $@
ifneq ($(PROG),)
# Build a standalone executable (unix and unix-cpy do this)
# Build a standalone executable (unix does this)
all: $(PROG)
......
......@@ -173,12 +173,6 @@
/*****************************************************************************/
/* Micro Python emitters */
// Whether to emit CPython byte codes (for debugging/testing)
// Enabling this overrides all other emitters
#ifndef MICROPY_EMIT_CPYTHON
#define MICROPY_EMIT_CPYTHON (0)
#endif
// Whether to emit x64 native code
#ifndef MICROPY_EMIT_X64
#define MICROPY_EMIT_X64 (0)
......
......@@ -548,7 +548,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
}
#if !MICROPY_EMIT_CPYTHON && !MICROPY_ENABLE_DOC_STRING
#if !MICROPY_ENABLE_DOC_STRING
// this code discards lonely statements, such as doc strings
if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
mp_parse_node_t p = peek_result(&parser, 1);
......@@ -559,7 +559,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
break;
}
}
#endif
#endif
// always emit these rules, even if they have only 1 argument
if (rule->rule_id == RULE_expr_stmt || rule->rule_id == RULE_yield_stmt) {
......
......@@ -32,7 +32,6 @@ PY_O_BASENAME = \
scope.o \
compile.o \
emitcommon.o \
emitcpy.o \
emitbc.o \
asmx64.o \
emitnx64.o \
......
......@@ -149,59 +149,3 @@ void scope_close_over_in_parents(scope_t *scope, qstr qst) {
}
assert(0); // we should have found the variable in one of the parents
}
#if MICROPY_EMIT_CPYTHON
#include <stdio.h>
void scope_print_info(scope_t *s) {
if (s->kind == SCOPE_MODULE) {
printf("code <module>\n");
} else if (s->kind == SCOPE_LAMBDA) {
printf("code <lambda>\n");
} else if (s->kind == SCOPE_LIST_COMP) {
printf("code <listcomp>\n");
} else if (s->kind == SCOPE_DICT_COMP) {
printf("code <dictcomp>\n");
} else if (s->kind == SCOPE_SET_COMP) {
printf("code <setcomp>\n");
} else if (s->kind == SCOPE_GEN_EXPR) {
printf("code <genexpr>\n");
} else {
printf("code %s\n", qstr_str(s->simple_name));
}
/*
printf("var global:");
for (int i = 0; i < s->id_info_len; i++) {
if (s->id_info[i].kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
printf(" %s", qstr_str(s->id_info[i].qst));
}
}
printf("\n");
printf("var name:");
for (int i = 0; i < s->id_info_len; i++) {
if (s->id_info[i].kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
printf(" %s", qstr_str(s->id_info[i].qst));
}
}
printf("\n");
printf("var local:");
for (int i = 0; i < s->id_info_len; i++) {
if (s->id_info[i].kind == ID_INFO_KIND_LOCAL) {
printf(" %s", qstr_str(s->id_info[i].qst));
}
}
printf("\n");
printf("var free:");
for (int i = 0; i < s->id_info_len; i++) {
if (s->id_info[i].kind == ID_INFO_KIND_FREE) {
printf(" %s", qstr_str(s->id_info[i].qst));
}
}
printf("\n");
*/
printf(" flags %04x\n", s->scope_flags);
printf(" argcount %d\n", s->num_pos_args);
printf(" nlocals %d\n", s->num_locals);
printf(" stacksize %d\n", s->stack_size);
}
#endif
......@@ -81,6 +81,5 @@ id_info_t *scope_find(scope_t *scope, qstr qstr);
id_info_t *scope_find_global(scope_t *scope, qstr qstr);
id_info_t *scope_find_local_in_parent(scope_t *scope, qstr qstr);
void scope_close_over_in_parents(scope_t *scope, qstr qstr);
void scope_print_info(scope_t *s);
#endif // __MICROPY_INCLUDED_PY_SCOPE_H__
output
mp-tests/__pycache__
pylib-tests/__pycache__
This directory contains the framework and test files for testing the byte code
output of the Micro Python compiler.
You need to first build the 'cpy' executable in the directory micropython/unix-cpy/.
This executable is a minimal version of Micro Python which compiles a single source
file and outputs the corresponding byte code.
The output of Micro Python is checked against CPython 3.4.
To run the tests use:
./run-tests
Note that the tests in pylib-test/ are from the Python 3.3 library, and are licensed
under the relevant license, as per pylib-test/LICENSE.txt.
import sys
name = sys.argv[1].split('/')[-1].split('.')[0]
with open(sys.argv[1]) as f:
lines_correct = [l.strip('\n') for l in f.readlines()]
lines_me = [l.strip('\n') for l in sys.stdin.readlines()]
if len(lines_me) != len(lines_correct):
if len(lines_me) == 0:
print('{:<20}: no output'.format(name))
elif lines_me[0].find('syntax error') >= 0:
print('{:<20}: syntax error'.format(name))
elif lines_me[0].find(' cannot be compiled') >= 0:
print('{:<20}: compile error: {}'.format(name, lines_me[0]))
else:
print('{:<20}: mismatch in number of lines'.format(name))
else:
total = len(lines_me)
same = 0
bad_num_fields = 0
bad_2 = 0
bad_3 = 0
jump_op = ['JUMP_FORWARD', 'JUMP_ABSOLUTE', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE', 'SETUP_LOOP']
jump_abs_op = ['JUMP_FORWARD', 'JUMP_ABSOLUTE']
for i in range(total):
if lines_me[i] == lines_correct[i]:
same += 1
else:
# line is different
line_me = lines_me[i].strip().split(' ', 2)
line_correct = lines_correct[i].strip().split(' ', 2)
allow = False
if len(line_me) != len(line_correct):
bad_num_fields += 1
elif len(line_me) == 2:
if line_me[0] == line_correct[0] == 'stacksize':
allow = True
else:
bad_2 += 1
else:
assert(len(line_me) == 3)
if line_me[0] == line_correct[0] and line_me[1] in jump_abs_op and line_correct[1] in jump_abs_op:
allow = True
elif line_me[0] == line_correct[0] and line_me[1] == line_correct[1] in jump_op:
allow = True
else:
bad_3 += 1
#if not allow:
# print(line_me, 'vs', line_correct)
bad_str = ''
if bad_num_fields > 0:
bad_str += ', {} bad num fields'.format(bad_num_fields)
if bad_2 > 0:
bad_str += ', {} bad 2-field'.format(bad_2)
if bad_3 > 0:
bad_str += ', {} bad 3-field'.format(bad_3)
print('{:<20}: {:>6} lines, {:>5.1f}% correct{}'.format(name, total, 100 * same / total, bad_str))
[] = ()
[] = []
a = b
(a) = b
a, b = c, d
a, b, c = d, e, f
a, b, c, d = e, f, g, h
#(a, b) = c, d
#a, b = (c, d)
#(a, b) = (c, d)
*a, = b
a, *b = c
a, *b, = c
a, *b, c = d
[*a] = b
[*a,] = b
[a, *b] = c
[a, *b,] = c
[a, *b, c] = d
(*a,) = x
(*a, b) = x
(a, *b) = x
(*a, b, c) = x
(a, *b, c) = x
(a, b, *c) = x
(*a, b, c, d) = x
(a, *b, c, d) = x
(a, b, *c, d) = x
(a, b, c, *d) = x
[] = ()
x += 1
x.y += 1
x.f().y += 1
x[1] += 2
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment