/Python/future.c

http://unladen-swallow.googlecode.com/ · C · 140 lines · 111 code · 17 blank · 12 comment · 51 complexity · 4ed7ea2db19ee5debe15db6951ba4c7c MD5 · raw file

  1. #include "Python.h"
  2. #include "Python-ast.h"
  3. #include "node.h"
  4. #include "token.h"
  5. #include "graminit.h"
  6. #include "code.h"
  7. #include "compile.h"
  8. #include "symtable.h"
  9. #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
  10. static int
  11. future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
  12. {
  13. int i;
  14. asdl_seq *names;
  15. assert(s->kind == ImportFrom_kind);
  16. names = s->v.ImportFrom.names;
  17. for (i = 0; i < asdl_seq_LEN(names); i++) {
  18. alias_ty name = (alias_ty)asdl_seq_GET(names, i);
  19. const char *feature = PyString_AsString(name->name);
  20. if (!feature)
  21. return 0;
  22. if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
  23. continue;
  24. } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
  25. continue;
  26. } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
  27. ff->ff_features |= CO_FUTURE_DIVISION;
  28. } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
  29. ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
  30. } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
  31. ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
  32. } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
  33. ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
  34. } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
  35. ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
  36. } else if (strcmp(feature, "braces") == 0) {
  37. PyErr_SetString(PyExc_SyntaxError,
  38. "not a chance");
  39. PyErr_SyntaxLocation(filename, s->lineno);
  40. return 0;
  41. } else {
  42. PyErr_Format(PyExc_SyntaxError,
  43. UNDEFINED_FUTURE_FEATURE, feature);
  44. PyErr_SyntaxLocation(filename, s->lineno);
  45. return 0;
  46. }
  47. }
  48. return 1;
  49. }
  50. static int
  51. future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
  52. {
  53. int i, found_docstring = 0, done = 0, prev_line = 0;
  54. static PyObject *future;
  55. if (!future) {
  56. future = PyString_InternFromString("__future__");
  57. if (!future)
  58. return 0;
  59. }
  60. if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
  61. return 1;
  62. /* A subsequent pass will detect future imports that don't
  63. appear at the beginning of the file. There's one case,
  64. however, that is easier to handle here: A series of imports
  65. joined by semi-colons, where the first import is a future
  66. statement but some subsequent import has the future form
  67. but is preceded by a regular import.
  68. */
  69. for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
  70. stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
  71. if (done && s->lineno > prev_line)
  72. return 1;
  73. prev_line = s->lineno;
  74. /* The tests below will return from this function unless it is
  75. still possible to find a future statement. The only things
  76. that can precede a future statement are another future
  77. statement and a doc string.
  78. */
  79. if (s->kind == ImportFrom_kind) {
  80. if (s->v.ImportFrom.module == future) {
  81. if (done) {
  82. PyErr_SetString(PyExc_SyntaxError,
  83. ERR_LATE_FUTURE);
  84. PyErr_SyntaxLocation(filename,
  85. s->lineno);
  86. return 0;
  87. }
  88. if (!future_check_features(ff, s, filename))
  89. return 0;
  90. ff->ff_lineno = s->lineno;
  91. }
  92. else
  93. done = 1;
  94. }
  95. else if (s->kind == Expr_kind && !found_docstring) {
  96. expr_ty e = s->v.Expr.value;
  97. if (e->kind != Str_kind)
  98. done = 1;
  99. else
  100. found_docstring = 1;
  101. }
  102. else
  103. done = 1;
  104. }
  105. return 1;
  106. }
  107. PyFutureFeatures *
  108. PyFuture_FromAST(mod_ty mod, const char *filename)
  109. {
  110. PyFutureFeatures *ff;
  111. ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
  112. if (ff == NULL) {
  113. PyErr_NoMemory();
  114. return NULL;
  115. }
  116. ff->ff_features = 0;
  117. ff->ff_lineno = -1;
  118. if (!future_parse(ff, mod, filename)) {
  119. PyObject_Free(ff);
  120. return NULL;
  121. }
  122. return ff;
  123. }