implementation module merge
import StdEnv, RWSDebug, StdArrayExtensions
from syntax import Optional, Yes, No
import utilities, portToNewSyntax
mergeFiles :: !*File !*File !*File -> (!.File,!.File,!.File)
mergeFiles old inferred new
# (lines_within_comment, old)
= lines_in_comment old
= merge_files lines_within_comment 0 old inferred new
merge_files :: ![Int] !Int !*File !*File !*File -> (!.File,!.File,!.File)
merge_files lines_within_comment line_nr old inferred new
# (end, old) = fend old
| end
# (inferred, new)
= copy_rest inferred new
= (old, inferred, new)
# (line, old) = my_freadline old
line_l = [ ch \\ ch<-:line ]
| not (begins_with_from line_l) || isMember line_nr lines_within_comment
= merge_files lines_within_comment (line_nr+1) old inferred (fwrites line new)
# new = fwrites ("//1.3\n"+++(complete_line line)) new
(new_line_nr, module_names, old, new)
= copy_original_from_statements line_nr line_l [] old new
// insert inferred part
new = fwrites ("//3.1\n/*2.0\n") new
(inferred, new)
= foldSt insert_inferred_from_stmnt module_names (inferred, new)
= merge_files lines_within_comment new_line_nr old inferred (fwrites "0.2*/\n" new)
copy_original_from_statements line_nr line_l mod_names_accu old new
# (left_space, module_name) = get_ls_and_mn line_l
(line_nr, opt_next_from_statement, old, new) = layout_skip line_nr left_space old new
= case opt_next_from_statement of
No
-> (line_nr, reverse [module_name:mod_names_accu], old, new)
Yes line_l`
-> copy_original_from_statements line_nr line_l` [module_name:mod_names_accu]
old new
insert_inferred_from_stmnt module_name (inferred, new)
# (first_line_of_import, inferred) = my_freadline inferred
new = foldSt fwrites ["from ", module_name, " ", first_line_of_import] new
= copy_rest_of_import inferred new
begins_with_from line_l
# without_spaces = dropWhile isSpace line_l
= case without_spaces of
['from'] -> True
['from',ch:_] -> not (isAlphanum ch || isMember ch ['`_'])
_ -> False
get_ls_and_mn line_l
# (spaces, rest1) = span isSpace line_l
without_from = drop 4 rest1
(_, rest2) = span isSpace without_from
module_name = takeWhile (not o isSpace) rest2
= (space_count spaces 0, toString module_name)
space_count [] _
= 0
space_count [' ':spaces] modTabWidth
= 1+(space_count spaces ((modTabWidth+1) mod modTabWidth))
space_count ['\t':spaces] modTabWidth
= (cTabWidth-modTabWidth)+(space_count spaces 0)
space_count ['\n':_] _
= 0
layout_skip :: !Int !Int !*File !*File -> (!Int, !Optional [Char], !.File, !.File)
layout_skip line_nr left_space old new
# (end, old) = fend old
| end
= (line_nr, No, old, new)
# (cur_pos, old) = fposition old
(line, old) = my_freadline old
line_l = [ ch \\ ch<-:line ]
spaces = takeWhile isSpace line_l
| space_count spaces 0<=left_space
| begins_with_from line_l
= (line_nr+1, Yes line_l, old, fwrites (complete_line line) new)
= (line_nr+1, No, snd (fseek old cur_pos FSeekSet), new)
= layout_skip (line_nr+1) left_space old (fwrites (complete_line line) new)
copy_rest_of_import :: !*File !*File -> (!.File, !.File)
copy_rest_of_import inferred new
# (end, inferred) = fend inferred
| end
= (inferred ,new)
# (cur_pos, inferred) = fposition inferred
(line, inferred) = my_freadline inferred
| line % (0,5)=="import"
= (snd (fseek inferred cur_pos FSeekSet), new)
= copy_rest_of_import inferred (fwrites line new)
complete_line line
| line.[size line-1]<>'\n'
= line+++"\n"
= line
copy_rest inferred new
# (end, inferred) = fend inferred
| end
= (inferred, new)
# (line, inferred)
= my_freadline inferred
= copy_rest inferred (fwrites line new)
lines_in_comment file
# (cur_pos, file)
= fposition file
(rev_lines_within_comment, file)
= get_lic 0 [] file
= (reverse rev_lines_within_comment, snd (fseek file cur_pos FSeekSet))
where
get_lic :: !Int ![Int] !*File -> (![Int], !*File)
get_lic line_nr line_nr_accu file
# (end, file)
= fend file
| end
= (line_nr_accu, file)
# (line, file)
= my_freadline file
line_l
= [ch \\ ch<-:line]
# (bwc, rest)
= begins_with_comment line_l
| bwc
= consider_comment 1 rest line_nr line_nr_accu file
= get_lic (line_nr+1) line_nr_accu file
begins_with_comment ['//1.3':rest]
= (True, rest)
begins_with_comment line_l
# without_spaces
= dropWhile isSpace line_l
= case without_spaces of
['/*':rest]
-> (True, rest)
_
-> (False, [])
consider_comment nesting_level ['*/':rest] line_nr line_nr_accu file
| nesting_level==1
= get_lic line_nr line_nr_accu file
= consider_comment (nesting_level-1) rest line_nr line_nr_accu file
consider_comment nesting_level ['/*':rest] line_nr line_nr_accu file
= consider_comment (nesting_level+1) rest line_nr line_nr_accu file
consider_comment nesting_level [_:rest] line_nr line_nr_accu file
= consider_comment nesting_level rest line_nr line_nr_accu file
consider_comment nesting_level [] line_nr line_nr_accu file
# (end, file)
= fend file
| end
= ([], file)
# (line, file)
= my_freadline file
line_l
= [ch \\ ch<-:line]
= case line_l of
['//3.1':rest]
| nesting_level==1
-> get_lic (line_nr+1) [line_nr+1:line_nr_accu] file
-> consider_comment (nesting_level-1) rest (line_nr+1) [line_nr+1:line_nr_accu] file
_
-> consider_comment nesting_level line_l (line_nr+1) [line_nr+1:line_nr_accu] file
my_freadline :: !*File -> (!String, !*File)
my_freadline file
#! (line, file) = freadline file
last_char_ix = size line - 1
last_printable_char_ix = findrArrElt isntNewlineOnAnyPlatform line last_char_ix
| last_printable_char_ix==(-1)
= ("\n", file)
| last_printable_char_ix==last_char_ix
= (line, file)
| last_printable_char_ix==last_char_ix-1 && line.[last_char_ix]=='\n'
= (line, file)
= ({line & [last_printable_char_ix+1] = '\n' } %(0, last_printable_char_ix+1), file)
isntNewlineOnAnyPlatform '\xA' = False
isntNewlineOnAnyPlatform '\xD' = False
isntNewlineOnAnyPlatform _ = True