diff --git a/mycpp/cppgen_pass.py b/mycpp/cppgen_pass.py index 001bc441a2..bd82364b67 100644 --- a/mycpp/cppgen_pass.py +++ b/mycpp/cppgen_pass.py @@ -52,6 +52,9 @@ def get_c_type(t): inner_c_type = get_c_type(type_param) c_type = 'List<%s>*' % inner_c_type + elif type_name == 'typing.IO': + c_type = 'runtime::IO*' + else: # fullname() => 'parse.Lexer'; name() => 'Lexer' @@ -283,7 +286,9 @@ def visit_member_expr(self, o: 'mypy.nodes.MemberExpr') -> T: if o.expr: # This is an approximate hack that assumes that locals don't shadow # imported names. Might be a problem with names like 'word'? - if isinstance(o.expr, NameExpr) and o.expr.name in self.imported_names: + expr_name = o.expr.name + if (isinstance(o.expr, NameExpr) and + (expr_name in self.imported_names or expr_name == 'runtime')): op = '::' else: op = '->' # Everything is a pointer @@ -331,9 +336,7 @@ def visit_call_expr(self, o: 'mypy.nodes.CallExpr') -> T: self.write('new ') # Namespace. - if callee_name == 'Buf': - self.write('runtime::Buf') - elif callee_name == 'int': # int('foo') in Python conflicts with keyword + if callee_name == 'int': # int('foo') in Python conflicts with keyword self.write('str_to_int') else: self.accept(o.callee) # could be f() or obj.method() diff --git a/mycpp/examples/files.py b/mycpp/examples/files.py index a534bcec9e..1622d17df9 100755 --- a/mycpp/examples/files.py +++ b/mycpp/examples/files.py @@ -7,13 +7,14 @@ import os import sys -from runtime import log, Buf +import runtime +from runtime import log def run_tests(): # type: () -> None - f = Buf() + f = runtime.Buf() for i in xrange(30): f.write(chr(i + 65)) @@ -21,9 +22,8 @@ def run_tests(): log('Wrote %d bytes to StringIO', len(contents)) log('contents = %s ... %s', contents[:10], contents[-10:]) - # TODO: - #f = sys.stdout - #f.write('stdout\n') + f2 = runtime.StdOut() + f2.write('stdout\n') def run_benchmarks(): @@ -34,7 +34,7 @@ def run_benchmarks(): i = 0 while i < n: - f = Buf() + f = runtime.Buf() for j in xrange(30): f.write(chr(i + 65)) diff --git a/mycpp/run.sh b/mycpp/run.sh index 8fe69ff74f..2767190830 100755 --- a/mycpp/run.sh +++ b/mycpp/run.sh @@ -313,7 +313,7 @@ python-example() { example-both() { local name=$1 - #mypy --py2 --strict examples/$name.py + mypy --py2 --strict examples/$name.py translate-example $name compile-example $name diff --git a/mycpp/runtime.cc b/mycpp/runtime.cc index 3e2ebc3998..4554fd4a17 100644 --- a/mycpp/runtime.cc +++ b/mycpp/runtime.cc @@ -143,20 +143,25 @@ Str* StrIter::Value() { namespace runtime { +IO* gStdOut; + void Buf::write(Str* s) { int orig_len = len_; len_ += s->len_; - if (data_ == nullptr) { // first write - data_ = static_cast(malloc(len_ + 1)); - } else { - data_ = static_cast(realloc(data_, len_ + 1)); - } + // data_ is nullptr at first + data_ = static_cast(realloc(data_, len_ + 1)); // Append to the end memcpy(data_ + orig_len, s->data_, s->len_); data_[len_] = '\0'; } +void CFile::write(Str* s) { + // note: throwing away the return value + fwrite(s->data_, s->len_, 1, f_); +} + + }; // diff --git a/mycpp/runtime.h b/mycpp/runtime.h index ae039ed344..ff8ee1db3a 100644 --- a/mycpp/runtime.h +++ b/mycpp/runtime.h @@ -8,6 +8,8 @@ #include // size_t #include // malloc #include // strlen +// https://stackoverflow.com/questions/3882346/forward-declare-file +#include // FILE* #include #include @@ -297,11 +299,16 @@ int str_to_int(Str* s); namespace runtime { // MyPy artifact -class Buf { +class IO { + public: + virtual void write(Str* s) = 0; +}; + +class Buf : public IO { public: Buf() : data_(nullptr), len_(0) { }; - void write(Str* s); + virtual void write(Str* s); Str* getvalue() { return new Str(data_, len_); } private: @@ -310,6 +317,26 @@ class Buf { size_t len_; }; +// Wrap a FILE* +class CFile : public IO { + public: + CFile(FILE* f) : f_(f) { + }; + virtual void write(Str* s); + + private: + FILE* f_; +}; + +extern IO* gStdOut; + +inline IO* StdOut() { + if (gStdOut == nullptr) { + gStdOut = new CFile(stdout); + } + return gStdOut; +} + }; #endif // RUNTIME_H diff --git a/mycpp/runtime.py b/mycpp/runtime.py index 9ee9741eb4..232380bd00 100644 --- a/mycpp/runtime.py +++ b/mycpp/runtime.py @@ -4,7 +4,7 @@ from __future__ import print_function import sys -from typing import Any +from typing import IO, Any # C code ignores this! @@ -25,3 +25,7 @@ def p_die(msg, *args): class Buf(StringIO.StringIO): pass + + +def StdOut(): + return sys.stdout diff --git a/mycpp/runtime.pyi b/mycpp/runtime.pyi new file mode 100644 index 0000000000..337e9c1b3f --- /dev/null +++ b/mycpp/runtime.pyi @@ -0,0 +1,9 @@ +from typing import IO, Any + +class Buf: + def write(self, s: str) -> None: ... + def getvalue(self) -> str: ... + +def StdOut() -> IO[bytes]: ... + +def log(msg: str, *args: Any) -> None: ...