From 84cc2eba5d1b10f267a78072c897083c20307a48 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alexis=20Laferri=C3=A8re?= Date: Thu, 18 Aug 2011 16:57:13 -0400 Subject: [PATCH] tools: adds nits, a compiler of help files to use the native interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Alexis Laferrière --- .gitignore | 2 + Makefile | 8 +- src/nits.nit | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile | 2 +- tests/sav/nits.sav | 11 +++ 5 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 src/nits.nit create mode 100644 tests/sav/nits.sav diff --git a/.gitignore b/.gitignore index a4d3ff1..d54ff3f 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ tests/alt tests/errlist tests/test_nitc_logs tests/hello_world + +*.stub.nit.[ch] diff --git a/Makefile b/Makefile index fa95668..117dad5 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ NITCOPT= -all: bin/nitc bin/nitdoc doc/stdlib/index.html +all: bin/nitc bin/nitdoc doc/stdlib/index.html bin/nits bin/nitc: c_src/nitc src/parser/parser.nit @echo '***************************************************************' @@ -32,6 +32,12 @@ bin/nitdoc: bin/nitc src/git-gen-version.sh bin/nitc ${NITCOPT} -o bin/nitdoc -O -v src/nitdoc.nit +bin/nits: bin/nitc + @echo '***************************************************************' + @echo '* Compile nits from NIT source files *' + @echo '***************************************************************' + bin/nitc ${NITCOPT} -o bin/nits -O -v src/nits.nit + doc/stdlib/index.html: bin/nitdoc @echo '***************************************************************' @echo '* Generate doc for NIT standard library *' diff --git a/src/nits.nit b/src/nits.nit new file mode 100644 index 0000000..d2c0742 --- /dev/null +++ b/src/nits.nit @@ -0,0 +1,209 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2011 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Stub generator for modules using the native interface +module nits + +import parser +import syntax +import metamodel +import analysis +import abstracttool +import native_interface + +class NitStubGenerator + super AbstractCompiler + + var opt_in_place: OptionBool = new OptionBool("Generate stub files as .nit.[ch] instead of .stub.nit.[ch]", "-i", "--in-place") + + init + do + super( "nits" ) + + option_context.add_option(opt_in_place) + end + + redef fun perform_work(mods) + do + for mod in mods do + assert mod isa MMSrcModule + + # TODO check if extern hybrid + + var visitor = new StubVisitor( opt_in_place.value ) + + # actually compil stub + mod.generate_stub( visitor ) + + # write to file + var mod_base_path = "{mod.directory.path}/{mod.name}" + visitor.write_to_files( mod_base_path ) + end + end +end + + +redef class MMModule + fun generate_stub( v: StubVisitor ) + do + ### header comments + var module_info = "/*\n\tExtern implementation of Nit module {name}\n" + v.header_head.add( module_info ) + v.body_head.add( module_info ) + + # instructions to rename + if not v.in_place then + v.header_head.add( "\tFile initially created by nits to implement extern methods body\n" ) + v.body_head.add( "\tFile initially created by nits to customize type of extern classes\n" ) + end + + v.header_head.add( "*/\n\n" ) + v.body_head.add( "*/\n\n" ) + ### end of header comments + + # header file guard + var guard = "{name.to_s.to_upper}_NIT_H" + v.header_head.add( "#ifndef {guard}\n#define {guard}\n\n" ) + + ### imports + # import standard .nit.h file + v.body_head.add( "#include \"{name}.nit.h\"\n" ) + + # import autogenerated frontier header file + v.header_head.add( "#include <{name}._nitni.h>\n\n" ) + ### end of import + + for local_class in local_classes do + ### extern methods + for prop in local_class.local_local_properties do + # if defined of redefined in this module + # and is extern + if prop.mmmodule == self and + prop isa MMSrcMethod and prop.is_extern then + prop.generate_stub( v ) + end + end + + ### extern classes + # if class is extern and defined here first + if local_class.global.intro == local_class and + local_class.global.is_extern then + local_class.generate_stub( v ) + end + end + + # header file guard close + v.header_head.add( "#endif\n" ) + end +end + +redef class MMSrcMethod + fun generate_stub( v: StubVisitor ) + do + ### documentation to guide the user + var helper_documentation = new Writer + + # title comment + helper_documentation.add( "C implementation of {full_name}" ) + + # TODO add nitdoc comment + + # explicit extern calls signatures in comment + var imported_signatures = new Array[String] + for extern_call in explicit_imports do + var meth = extern_call.method + imported_signatures.add( "\t{meth.friendly_csignature(extern_call.local_class)} for {meth.full_name}" ) + end + + # explicit extern casts + for cast in explicit_casts do + if not ( cast.is_about_nullable_only and + cast.is_not_null_to_nullable ) then + imported_signatures.add( "\t{cast.is_a_friendly_csignature} to check if a {cast.from} is a {cast.to}" ) + end + + imported_signatures.add( "\t{cast.as_friendly_csignature} to cast from {cast.from} to {cast.to}" ) + end + + # explicit extern casts + if need_super then + imported_signatures.add( "\t{friendly_super_csignature} to call super" ) + end + + if imported_signatures.length > 0 then + helper_documentation.add("\n\nImported methods signatures:\n" ) + helper_documentation.add_all( imported_signatures, "\n") + end + + v.body_impl.add( "\n/*\n" ) + v.body_impl.append( helper_documentation ) + v.body_impl.add( "\n*/\n" ) + ### end of documentation + + ### extern method implementation + v.header_decl.add( "{impl_csignature};\n" ) + + v.body_impl.add( "{impl_csignature} \{" ) + + v.body_impl.add( "\}\n" ) + ### end of implementation + end +end + +redef class MMLocalClass + fun generate_stub( v: StubVisitor ) + do + v.header_head.add( "#define {get_type.friendly_extern_name} void*\n" ) + end +end + +class StubVisitor + # comments, imports (auto and custom from inline), types + var header_head : Writer = new Writer + + # implementation declaration for extern methods + var header_decl : Writer = new Writer + + # comments, imports and custom code from inline + var body_head : Writer = new Writer + + # implementation body of extern methods + var body_impl : Writer = new Writer + + # generates final .nit.[ch] instead of stub files .sub.nit.[ch] + var in_place : Bool + + init ( in_place : Bool ) do self.in_place = in_place + + # write stubs to disk + fun write_to_files( base_path : String ) + do + var mid_ext = if in_place then ".nit" else ".stub.nit" + + var stream = new OFStream.open( "{base_path}{mid_ext}.h" ) + header_head.write_to_stream( stream ) + header_decl.write_to_stream( stream ) + stream.close + + stream = new OFStream.open( "{base_path}{mid_ext}.c" ) + body_head.write_to_stream( stream ) + body_impl.write_to_stream( stream ) + stream.close + end +end + +var nits = new NitStubGenerator +nits.exec_cmd_line diff --git a/tests/Makefile b/tests/Makefile index a45286a..b75c520 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,7 +8,7 @@ some: ./tests.sh base_compile.nit base_attr.nit base_gen.nit test_gen_inh.nit bench_fib.nit example_objet.nit global: - ./tests.sh -o --global *.nit ../examples/*.nit ../lib/*.nit ../src/nitdoc.nit ../src/nitc.nit ../src/test_parser.nit + ./tests.sh -o --global *.nit ../examples/*.nit ../lib/*.nit ../src/nitdoc.nit ../src/nitc.nit../src/nits.nit ../src/test_parser.nit icode: ./tests_icode.sh icode*.nit diff --git a/tests/sav/nits.sav b/tests/sav/nits.sav new file mode 100644 index 0000000..92b0452 --- /dev/null +++ b/tests/sav/nits.sav @@ -0,0 +1,11 @@ +usage: nits [options] file... + -W, --warn Show warnings + -I, --path Set include path for loaders (may be used more than once) + --log Generate various log files + --log-dir Directory where to generate log files + --only-parse Only proceed to parse step of loaders + --only-metamodel Stop after meta-model processing + -h, -?, --help Show Help (This screen) + --version Show version and exit + -v, --verbose Verbose + -i, --in-place Generate stub files as .nit.[ch] instead of .stub.nit.[ch] -- 1.7.9.5