diff options
Diffstat (limited to 'portToNewSyntax')
-rw-r--r-- | portToNewSyntax/help.txt | 142 | ||||
-rw-r--r-- | portToNewSyntax/portToNewSyntax.dcl | 22 | ||||
-rw-r--r-- | portToNewSyntax/portToNewSyntax.icl | 263 | ||||
-rw-r--r-- | portToNewSyntax/readme.txt | 20 |
4 files changed, 447 insertions, 0 deletions
diff --git a/portToNewSyntax/help.txt b/portToNewSyntax/help.txt new file mode 100644 index 0000000..17155f5 --- /dev/null +++ b/portToNewSyntax/help.txt @@ -0,0 +1,142 @@ + coclPort - a tool to port Clean 1.3 programs to Clean 2.0 + ---------------------------------------------------------------------------- + +Folder contents +--------------- + + coclPort.exe - a tool to port Clean 1.3 programs to Clean 2.0 + StdEnvPort - a necessary standard environment + help.txt - this file + + +Why to use coclPort +------------------- + + Clean 2.0 is not downward compatible to Clean 1.3.x: Due to changes in the + syntax there are Clean 1.3.x programs that cannot be compiled with the new + Clean 2.0 compiler. Fortunately these changes in syntax are rather small. + The most important syntax modification is concerned with explicit + import statements. These are statements like "from m import x". With the + new syntax it's possible to write e.g. + + from m import T, :: T (C1), :: T2 (..), class ==, instance == Int + + Such a statement causes the following symbols to be imported: the function T, + the algebraic type T with it's constructor C1, the algebraic type T2 with all + it's constructors, the class == and it's instance Int. See the Clean 2.0 + language report for further information. + + Purpose of coclPort is to help you to port Clean 1.3.x programs to + this new syntax. + +What coclPort does +------------------ + + coclPort is indeed a Clean 2.0 compiler that is modified such that it can + handle Clean 1.3 import syntax. Therefore it cannot handle 2.0 import syntax. + To port a 1.3 module + just compile it with the coclPort compiler. Then for this "original" module + a copy of that module is written out in which the explicit import + statements have been adapted to Clean 2.0 syntax. This copy will be written + into a folder named "PortedModules" which will be a subfolder of the folder + that contains the original module. + + Due to some other slight changes + in the language it is possible that your Clean 1.3.x modules will not be accepted + by coclPort. For instance the "String" type has become a + basic type (so you can't import it explicitly). + In that case you have to modify the contents of the original module + and try again. + + coclPort has some insufficiencies. See section "Insufficiencies". + +The preprocessor +---------------- + + We think that for a while it should be made possible to let every source code + file be compiled with both the 1.3 and the 2.0 compiler. How can this be + achieved when the 2.0 compiler is not fully downward compatible? With a + preprocessor of course. The simple preprocessor that we have built into + coclPort and into the 2.0 compiler as well allows to distinguish parts + of code that are either ignored by + the 1.3 compiler or by the 2.0 compiler. To illustrate this we show what + coclPort will produce for a file that contains the following statement: + + from module_name import == + + The produced output might look like this: + + //1.3 + from module_name import == + //3.1 + /*2.0 + from module_name import class ==, instance == Int, instance == Real + 0.2*/ + + For the 2.0 compiler this would be the same as + + from module_name import class ==, instance == Int, instance == Real + + because the preprocessor will take care that everything between "//1.3" and + "//3.1" will be ignored and that everything between "/*2.0" and "0.2*/" + will _not_ be treated as a comment. + For the 1.3 this would be the same as + + from module_name import == + + You can use this feature to keep your files both compilable with 1.3 and + with 2.0. If you don't want your sources cluttered with old 1.3 stuff then + you can use the "rmPreprop" application to extract the pure 1.3 or 2.0 + contents. + Note that the "//1.3", "//3.1", "/*2.0" and "0.2*/" brackets have to be + the first characters of the line (no preceeding whitespace characters are + allowed). Otherwise they will be ignored. Furtheron such sections shouldn't + be nested or overlapping. + +How to use this program +----------------------- + + You have to tell the CleanIDE that for compiling a module it should + launch "coclPort.exe" instead "cocl.exe" (BTW "cocl" means "Concurrent + Clean"). In the CleanIDE select an environment that uses the Clean 2.0 + compiler. Now select "Environment/Edit Current" and select the "tools" + button. The field at "compiler:" determines where the CleanIDE finds the + Clean commpiler (cocl.exe). You can use this field to ensure that this entry indeed + refers to the Clean 2.0 compiler and not e.g. to a Clean 1.3 compiler: + If it is the Clean 2.0 compiler then there must be a file named "backend.dll" + in the folder that is shown there. Put the file "coclPort.exe" into the same + folder and change the entry in the field at "compiler:" from "cocl.exe" + into "coclPort.exe". Now the CleanIDE will use coclPort as the compiler. + + But coclPort needs another standard environment than cocl. You have to replace + the path to StdEnv to a path to StdEnvPort. You can set paths with the + "Environment/Edit Current" or "Project/Project Options" dialog. + + Now simply try to compile your project. + +Insufficiencies +--------------- + + Certain restrictions are imposed on the source code that should be ported: + - For every explicit import statement the "from" token should be the first + non white space character in that line. After some white space characters + the line should then contain the module name (and not e.g. a comment first). + This excludes the following import statements + /* comment */ from module_name import f + from /* comment */ module_name import f + from + module_name import f + An explicit import statement that is outcommented with "//" will work fine, + since it will be ignored anyway: + // from module_name import f + - coclPort has problems when a line within a comment begins + with the "from" token this can be mistaken as an explicit import statement + by this program. As a consequence in the "ported" version there might appear + an explicit import statement within that comment that should appear somewhere + else. Example: + import aphrotisaica /* And I knew I loved her + from that moment on until forever */ + However we think that when something goes wrong with this program it should + be easy to adjust the ported modules manually after it has been tried to + compile them. +
\ No newline at end of file diff --git a/portToNewSyntax/portToNewSyntax.dcl b/portToNewSyntax/portToNewSyntax.dcl new file mode 100644 index 0000000..ebec5e4 --- /dev/null +++ b/portToNewSyntax/portToNewSyntax.dcl @@ -0,0 +1,22 @@ +definition module portToNewSyntax + +from StdMisc import abort +//1.3 +from StdFile import Files +from StdString import String +from scanner import SearchPaths +//3.1 +/*2.0 +from StdFile import :: Files +from scanner import :: SearchPaths +0.2*/ +import checksupport + +switch_port_to_new_syntax port dont_port :== port + +cTabWidth :== 4 + +writeExplImportsToFile :: !String ![([Declaration],a)] !{#u:DclModule} !*CheckState + -> (!{#u:DclModule},!.CheckState) + +createPortedFiles :: !String !SearchPaths !*Files -> (!Bool, !*Files) diff --git a/portToNewSyntax/portToNewSyntax.icl b/portToNewSyntax/portToNewSyntax.icl new file mode 100644 index 0000000..85dbef8 --- /dev/null +++ b/portToNewSyntax/portToNewSyntax.icl @@ -0,0 +1,263 @@ +implementation module portToNewSyntax + +import StdEnv, scanner, Directory, merge, checksupport + +switch_port_to_new_syntax port dont_port :== port + +cTabWidth :== 4 + +resultFolderName =: "PortedModules" + +createPortedFiles :: !String !SearchPaths !*Files -> (!Bool, !*Files) +createPortedFiles fileName searchPaths files + # (ok, files) + = case findDirOfModule fileName searchPaths files of + (No, files) + -> (False, files) + (Yes path, files) + # (ok, files) + = ensureSubDirExists path fileName files + | not ok + -> (ok, files) + # (ok1, files) + = tryToCreatePortedFile fileName "icl" path files + (ok2, files) + = tryToCreatePortedFile fileName "dcl" path files + -> (ok1&&ok2, files) + (_, files) + = fremove (RelativePath [PathDown "icl.txt"]) files + (_, files) + = fremove (RelativePath [PathDown "dcl.txt"]) files + = (ok, files) + + +tryToCreatePortedFile :: !String !String !Path !*Files -> (!Bool,!*Files) +tryToCreatePortedFile file_name suffix path ms_files + # with_suffix + = file_name+++"."+++suffix + # (old_module_filename, ms_files) + = pathToPD_String (pathAppend path [PathDown with_suffix]) ms_files + (ok, old, ms_files) = fopen old_module_filename FReadData ms_files + | not ok + = (ok, ms_files) + # (new_module_filename, ms_files) + = pathToPD_String (pathAppend path [PathDown resultFolderName, + PathDown with_suffix]) ms_files + inferred_filename = suffix+++".txt" + (ok1, inferred, ms_files) = fopen inferred_filename FReadText ms_files + (ok2, new, ms_files) = fopen new_module_filename FWriteText ms_files + | not (ok1&&ok2) + = (False, ms_files) + # (old, inferred, new) = mergeFiles old inferred new + (ok3, ms_files) = fclose old ms_files + (ok4, ms_files) = fclose inferred ms_files + (ok5, ms_files) = fclose new ms_files + = (ok3&&ok4&&ok5, ms_files) + +findDirOfModule :: !{#Char} !SearchPaths *Files -> (!Optional Path, !*Files) +findDirOfModule fileName searchPaths files + # filtered_locations + = filter (\(moduleName,pd_path) -> moduleName == fileName) searchPaths.sp_locations + | not (isEmpty filtered_locations) + # ((ok, path), files) + = pd_StringToPath (snd (hd filtered_locations)) files + | not ok + = (No, files) + = (Yes path, files) + = loop searchPaths.sp_paths (fileName+++".icl") files + where + loop :: ![String] !String !*Files -> (!Optional Path, !*Files) + loop [] _ files + = (No, files) + loop [pd_path:pd_paths] fileName files + # ((ok, path), files) + = pd_StringToPath pd_path files + | not ok + = (No, files) + # ((dir_error, _), files) + = getFileInfo (pathAppend path [PathDown fileName]) files + | dir_error == NoDirError + = (Yes path, files) + = loop pd_paths fileName files + +pathAppend (RelativePath p) x = RelativePath (p++x) +pathAppend (AbsolutePath diskname p) x = AbsolutePath diskname (p++x) + +ensureSubDirExists path fileName files + # path_result_folder = pathAppend path [PathDown resultFolderName] + ((err_code, _), files) = getFileInfo path_result_folder files + (errorCode, files) = case err_code of + NoDirError -> (NoDirError, files) + _ -> createDirectory path_result_folder files + = (errorCode==NoDirError, files) + + + + +writeExplImportsToFile :: !String ![([Declaration],a)] !{#u:DclModule} !*CheckState + -> (!{#u:DclModule},!.CheckState) +writeExplImportsToFile file_name si_explicit dcl_modules cs + # (file, cs) + = openFile file_name cs + (dcl_modules, file) + = foldSt (write_expl_import (flatten (map fst si_explicit))) (reverse si_explicit) (dcl_modules, file) + = (dcl_modules, closeFile file cs) + +write_expl_import all_expl_imp_decls (declarations, _) (dcl_modules, file) + # (declaration_strings, dcl_modules) + = mapFilterYesSt (decl_to_opt_string all_expl_imp_decls) (reverse declarations) dcl_modules + = (dcl_modules, fwriteNewSyntax declaration_strings file) + +// only for portToNewSyntax +decl_to_opt_string all_expl_imp_decls decl=:{dcl_ident, dcl_index, dcl_kind=STE_Imported ste_kind def_mod_index} + dcl_modules + = imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index ste_kind def_mod_index + dcl_modules +decl_to_opt_string _ {dcl_ident, dcl_kind=STE_FunctionOrMacro _} dcl_modules + = (Yes dcl_ident.id_name, dcl_modules) +decl_to_opt_string all_expl_imp_decls decl dcl_modules + = abort ("decl_to_opt_string failed"--->decl) + +// only for portToNewSyntax +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index STE_Constructor def_mod_index + dcl_modules + = (No, dcl_modules) +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index STE_Member def_mod_index + dcl_modules + = (No, dcl_modules) +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index STE_DclFunction def_mod_index + dcl_modules + = (Yes dcl_ident.id_name, dcl_modules) +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index STE_Class def_mod_index + dcl_modules + = (Yes ("class "+++dcl_ident.id_name+++"(..)"), dcl_modules) +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index (STE_Instance _) def_mod_index + dcl_modules + # ({ins_type}, dcl_modules) + = dcl_modules![def_mod_index].dcl_common.com_instance_defs.[dcl_index] + = (Yes ("instance "+++dcl_ident.id_name+++" "+++ + separated " " (map type_to_string ins_type.it_types)), dcl_modules) +imported_decl_to_opt_string all_expl_imp_decls dcl_ident dcl_index STE_Type def_mod_index + dcl_modules + # ({td_rhs}, dcl_modules) + = dcl_modules![def_mod_index].dcl_common.com_type_defs.[dcl_index] + dcl_string + = ":: "+++(case td_rhs of + AlgType constructors + -> dcl_ident.id_name+++constructor_bracket def_mod_index all_expl_imp_decls constructors + RecordType _ + -> dcl_ident.id_name+++"{..}" + _ + -> dcl_ident.id_name) + = (Yes dcl_string, dcl_modules) + +// only for portToNewSyntax +type_to_string (TA {type_name} _) = possibly_replace_predef_symbols type_name.id_name +type_to_string (TB type) = toString type +type_to_string (TV {tv_name}) = tv_name.id_name +type_to_string x = abort ("bug nr 945 in module check"--->x) + +possibly_replace_predef_symbols s + | s=="_list" + = "[]" + | s % (0,5) == "_tuple" + = (toString ['(':repeatn ((toInt (s%(6, (size s) - 1))) - 1) ','])+++")" + | s=="_array" + = "{}" + | s=="_!array" + = "{!}" + | s=="_#array" + = "{#}" + = s + +instance toString BasicType + where + toString BT_Int = "Int" + toString BT_Char = "Char" + toString BT_Real = "Real" + toString BT_Bool = "Bool" + toString BT_Dynamic = "Dynamic" + toString BT_File = "File" + toString BT_World = "World" + toString _ = abort "bug nr 346 in module check" + +// only for portToNewSyntax +separated _ [] + = "" +separated separator [h:t] + = foldl (\l r->l+++separator+++r) h t + +constructor_bracket def_mod_index all_expl_imp_decls constructors + # expl_imp_constructor_strings + = [ ds_ident.id_name \\ {ds_ident} <- constructors + | is_expl_imported_constructor def_mod_index ds_ident all_expl_imp_decls ] + | isEmpty expl_imp_constructor_strings + = "" + = "("+++separated "," expl_imp_constructor_strings+++")" + +// only for portToNewSyntax +is_expl_imported_constructor def_mod_index ds_ident [] + = False +is_expl_imported_constructor def_mod_index ds_ident [{dcl_ident, dcl_kind=STE_Imported STE_Constructor def_mod_index2}:_] + | dcl_ident==ds_ident && def_mod_index==def_mod_index2 + = True + // GOTO next alternative +is_expl_imported_constructor def_mod_index ds_ident [h:t] + = is_expl_imported_constructor def_mod_index ds_ident t + +fwriteNewSyntax importStrings file + | isEmpty importStrings + = fwrites "import @#$@@!!" file + # with_commas = (map (\s->s+++", ") (butLast importStrings))++[last importStrings+++";"] + lines = split_in_lines 12 with_commas [] [] + lines = [hd lines:[["\t":line]\\ line<-tl lines]] + line_strings = [ foldl (+++) " " (line++["\n"]) \\ line<-lines ] + = fwrites (foldl (+++) "import" line_strings) file + where + max_line_length = 80 + split_in_lines i [] inner_accu outer_accu + # accu = if (isEmpty inner_accu) outer_accu [reverse inner_accu:outer_accu] + = reverse accu + split_in_lines i [h:t] inner_accu outer_accu + # s = size h + | s+i>max_line_length + | isEmpty inner_accu + = split_in_lines (s+i) t [h] outer_accu + = split_in_lines (s+cTabWidth) t [h] [inner_accu:outer_accu] + = split_in_lines (s+i) t [h:inner_accu] outer_accu +// only for portToNewSyntax + +butLast [] = [] +butLast [x] = [] +butLast [h:t] = [h: butLast t] + +// MW: fake.. +openFile file_name cs + # world = bigBang + (ok, newFile, world) = fopen file_name FWriteText world + cs = forget world cs + cs = case ok of + True -> cs + _ # cs_error = checkError "" ("can't open file \""+++file_name+++" in current directory.") cs.cs_error + -> { cs & cs_error=cs_error } + = (newFile, cs) + +closeFile file cs + # world = bigBang + (ok, world) = fclose file world + = forget world cs + +bigBang :: .World +bigBang = cast 1 +// creates a world from scratch + +forget :: !.x !.y -> .y +forget x y = y + +cast :: !.a -> .b +cast a + = code + { + pop_a 0 + } +// ..fake diff --git a/portToNewSyntax/readme.txt b/portToNewSyntax/readme.txt new file mode 100644 index 0000000..b1dc277 --- /dev/null +++ b/portToNewSyntax/readme.txt @@ -0,0 +1,20 @@ +This file explains how to build a valid cocl that reads +Clean 1.3 sources and as a sideeffect produces sources +in which the explicit import statements have been +ported to 2.0 syntax ("coclPort" application) + +The module portToNewSyntax appears twice: in the "compiler" +folder and in the "portToNewSyntax" folder. Iff you want +to build coclPort then set the paths in such a way that +the portToNewSyntax.dcl/icl files from the portToNewSyntax +folder are preferred over the same files in the compiler +folder. + +Further set the "switch_import_syntax" macro in module +syntax to "one_point_three" + +The "switch_port_to_new_syntax" macro in module +portToNewSyntax is used to ed/disable the porting +facilities: +portToNewSyntax/portToNewSyntax.dcl: port +compiler/portToNewSyntax.dcl: dont_port |