aboutsummaryrefslogtreecommitdiff
path: root/portToNewSyntax
diff options
context:
space:
mode:
Diffstat (limited to 'portToNewSyntax')
-rw-r--r--portToNewSyntax/help.txt142
-rw-r--r--portToNewSyntax/portToNewSyntax.dcl22
-rw-r--r--portToNewSyntax/portToNewSyntax.icl263
-rw-r--r--portToNewSyntax/readme.txt20
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