comparison src/compiler.sml @ 1090:e77079953308

Module roots
author Adam Chlipala <adamc@hcoop.net>
date Thu, 24 Dec 2009 16:35:09 -0500
parents f1647f16097d
children 6f4b05fc4361
comparison
equal deleted inserted replaced
1089:f1647f16097d 1090:e77079953308
641 } 641 }
642 642
643 fun capitalize "" = "" 643 fun capitalize "" = ""
644 | capitalize s = str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE) 644 | capitalize s = str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE)
645 645
646 structure SM = BinaryMapFn(struct
647 type ord_key = string
648 val compare = String.compare
649 end)
650
651 val moduleRoots = ref ([] : (string * string) list)
652 fun addModuleRoot (k, v) = moduleRoots := (k, v) :: !moduleRoots
653
654 structure SS = BinarySetFn(struct
655 type ord_key = string
656 val compare = String.compare
657 end)
658
646 val parse = { 659 val parse = {
647 func = fn {database, sources = fnames, ffi, ...} : job => 660 func = fn {database, sources = fnames, ffi, ...} : job =>
648 let 661 let
662 val mrs = !moduleRoots
663
649 val anyErrors = ref false 664 val anyErrors = ref false
650 fun checkErrors () = anyErrors := (!anyErrors orelse ErrorMsg.anyErrors ()) 665 fun checkErrors () = anyErrors := (!anyErrors orelse ErrorMsg.anyErrors ())
651 fun nameOf fname = capitalize (OS.Path.file fname) 666 fun nameOf fname = capitalize (OS.Path.file fname)
652 667
653 fun parseFfi fname = 668 fun parseFfi fname =
662 val sgn = (Source.SgnConst (#func parseUrs urs), loc) 677 val sgn = (Source.SgnConst (#func parseUrs urs), loc)
663 in 678 in
664 checkErrors (); 679 checkErrors ();
665 (Source.DFfiStr (mname, sgn), loc) 680 (Source.DFfiStr (mname, sgn), loc)
666 end 681 end
682
683 val defed = ref SS.empty
667 684
668 fun parseOne fname = 685 fun parseOne fname =
669 let 686 let
670 val mname = nameOf fname 687 val mname = nameOf fname
671 val ur = OS.Path.joinBaseExt {base = fname, ext = SOME "ur"} 688 val ur = OS.Path.joinBaseExt {base = fname, ext = SOME "ur"}
684 val loc = {file = ur, 701 val loc = {file = ur,
685 first = ErrorMsg.dummyPos, 702 first = ErrorMsg.dummyPos,
686 last = ErrorMsg.dummyPos} 703 last = ErrorMsg.dummyPos}
687 704
688 val ds = #func parseUr ur 705 val ds = #func parseUr ur
706 val d = (Source.DStr (mname, sgnO, (Source.StrConst ds, loc)), loc)
707
708 val d = case List.find (fn (root, name) =>
709 String.isPrefix (root ^ "/") fname) mrs of
710 NONE => d
711 | SOME (root, name) =>
712 let
713 val fname = String.extract (fname, size root + 1, NONE)
714 val pieces = name :: String.tokens (fn ch => ch = #"/") fname
715 val pieces = List.filter (fn s => size s > 0
716 andalso Char.isAlpha (String.sub (s, 0)))
717 pieces
718 val pieces = map capitalize pieces
719
720 fun makeD prefix pieces =
721 case pieces of
722 [] => (ErrorMsg.error "Empty module path";
723 (Source.DStyle "Boo", loc))
724 | [_] => d
725 | piece :: pieces =>
726 let
727 val this = prefix ^ "." ^ piece
728 val old = SS.member (!defed, this)
729 in
730 defed := SS.add (!defed, this);
731 (Source.DStr (piece, NONE,
732 (Source.StrConst (if old then
733 [(Source.DOpen (piece, []),
734 loc),
735 makeD prefix pieces]
736 else
737 [makeD prefix pieces]), loc)),
738 loc)
739 end
740 in
741 makeD "" pieces
742 end
689 in 743 in
690 checkErrors (); 744 checkErrors ();
691 (Source.DStr (mname, sgnO, (Source.StrConst ds, loc)), loc) 745 d
692 end 746 end
693 747
694 val dsFfi = map parseFfi ffi 748 val dsFfi = map parseFfi ffi
695 val ds = map parseOne fnames 749 val ds = map parseOne fnames
750 val loc = ErrorMsg.dummySpan
696 in 751 in
697 if !anyErrors then 752 if !anyErrors then
698 ErrorMsg.error "Parse failure" 753 ErrorMsg.error "Parse failure"
699 else 754 else
700 (); 755 ();
701 756
702 let 757 let
703 val final = nameOf (List.last fnames) 758 val final = nameOf (List.last fnames)
704 759
705 val ds = dsFfi @ ds 760 val ds = dsFfi @ ds
706 @ [(Source.DExport (Source.StrVar final, ErrorMsg.dummySpan), ErrorMsg.dummySpan)] 761 @ [(Source.DExport (Source.StrVar final, loc), loc)]
762
763 val ds = case database of
764 NONE => ds
765 | SOME s => (Source.DDatabase s, loc) :: ds
707 in 766 in
708 case database of 767 ds
709 NONE => ds
710 | SOME s => (Source.DDatabase s, ErrorMsg.dummySpan) :: ds
711 end handle Empty => ds 768 end handle Empty => ds
712 end, 769 end,
713 print = SourcePrint.p_file 770 print = SourcePrint.p_file
714 } 771 }
715 772