Reader

include ivylang
include io
include error
include sys

instance env : environment(str)

object ivy = { ...

    instance file : file_io(str,str)

    action write_file(name:str,buf:str) = {
        var ok := file.write(name,buf);
        if ~ok {
            var ann : annot;
            call report_error(cannot_write.make(name),ann);
        }
    }

    var include_path : vector[str]

    after init {
        var inc := env.get("IVY_INCLUDE_PATH");
        var start := inc.begin;
        var idx := inc.begin;
        while idx < inc.end {
            if inc.value(idx) = 58 {  # colon
                if idx > start {
                    include_path := include_path.append(inc.segment(start,idx));
                };
                start := idx.next;
            };
            idx := idx.next
        };
        if idx > start {
            include_path := include_path.append(inc.segment(start,idx));
        }
    }


    object prog = { ...

        type readst = struct {
            have_read : ident_set
        }

        action find_include(name:str) returns (name:str) = {
            name := name.extend(".ivy");
            if ~file.exist(name) {
                var idx := include_path.begin;
                var found := false;
                while ~found & idx < include_path.end {
                    var pname := path.concat(include_path.value(idx),name);
                    if file.exist(pname) {
                        name := pname;
                        found := true
                    };
                    idx := idx.next;
                }
            }
        }

        action read_file_int(name:str,ann:annot,p:prog,rst:readst) returns (p:prog,rst:readst) = {
            var text : str;
            var ok : bool;
            (text,ok) := file.read(name,text);
            if ok {
                var st := pstate.make(text);
        st.ann.file := name;
                (st,p) := prog.parse_to(st,0,p);
                ok := st.ok & st.tok.end = 0;
                if ok {
                    var idx := p.decls.begin;
                    while idx < p.decls.end & errors.end = 0 {
                        var d := p.decls.value(idx);
                        if d isa includedc {
                var sname := d.get_expr;
                if ~(sname isa symbol) {
                call report_error(bad_syntax.make(sname),sname.get_ann);
                } else {
                var iname := sname.get_name;
                if ~rst.have_read.mem(iname) {
                    var fname := find_include(iname.to_str);
                    var subp : prog;
                    (subp,rst) := read_file_int(fname,d.get_ann,subp,rst);
                    p.decls := p.decls.set(idx,groupdc.make(subp.decls));
                    rst.have_read := rst.have_read.set(iname,true);
                }
                }
                        };
                        idx := idx.next
                    }
                } else {
                    var foo := syntax_error.make(st.tok);
                    call report_error(foo,st.ann);
                }
            } else {
                var foo := file_not_found.make(name);
                call report_error(foo,ann);
            }
        }
Read the main file, named name. We prepend include ivy to the file, to cause the standard preamble to be read.

        action read_file(name:str) returns (p:prog) = {
            var ann:annot;
            p.decls := p.decls.append(includedc.make(symbol.makestr("ivy",ann),ann));
            var rst : readst;
            (p,rst) := read_file_int(name,ann,p,rst);
        }

    }

    instance path : path_name(str)

}