storename := array[Dend] of{ Dtype => "type", Dfn => "function", Dglobal => "global", Darg => "argument", Dlocal => "local", Dconst => "con", Dfield => "field", Dtag => "pick tag", Dimport => "import", Dunbound => "unbound", Dundef => "undefined", Dwundef => "undefined",}; storeart := array[Dend] of{ Dtype => "a ", Dfn => "a ", Dglobal => "a ", Darg => "an ", Dlocal => "a ", Dconst => "a ", Dfield => "a ", Dtag => "a ", Dimport => "an ", Dunbound => "", Dundef => "", Dwundef => "",}; storespace := array[Dend] of{ Dtype => 0, Dfn => 0, Dglobal => 1, Darg => 1, Dlocal => 1, Dconst => 0, Dfield => 1, Dtag => 0, Dimport => 0, Dunbound => 0, Dundef => 0, Dwundef => 0,}; impdecl: ref Decl;impdecls: ref Dlist;scopes := array[MaxScope] of ref Decl;tails := array[MaxScope] of ref Decl;scopekind := array[MaxScope] of byte;scopenode := array[MaxScope] of ref Node;iota: ref Decl;zdecl: Decl; popscopes(){ d: ref Decl; # # clear out any decls left in syms # while(scope >= ScopeBuiltin){ for(d = scopes[scope--]; d != nil; d = d.next){ if(d.sym != nil){ d.sym.decl = d.old; d.old = nil; } } } for(id := impdecls; id != nil; id = id.next){ for(d = id.d.ty.ids; d != nil; d = d.next){ d.sym.decl = nil; d.old = nil; } } impdecls = nil; scope = ScopeBuiltin; scopes[ScopeBuiltin] = nil; tails[ScopeBuiltin] = nil;} declstart(){ iota = mkids(nosrc, enter("iota", 0), tint, nil); iota.init = mkconst(nosrc, big 0); scope = ScopeNils; scopes[ScopeNils] = nil; tails[ScopeNils] = nil; nildecl = mkdecl(nosrc, Dglobal, tany); nildecl.sym = enter("nil", 0); installids(Dglobal, nildecl); d := mkdecl(nosrc, Dglobal, tstring); d.sym = enterstring(""); installids(Dglobal, d); scope = ScopeGlobal; scopes[ScopeGlobal] = nil; tails[ScopeGlobal] = nil;} redecl(d: ref Decl){ old := d.sym.decl; if(old.store == Dwundef) return; error(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "+storeconv(old)+" on line "+ lineconv(old.src.start));} checkrefs(d: ref Decl){ id, m: ref Decl; refs: int; for(; d != nil; d = d.next){ if(d.das != byte 0) d.refs--; case d.store{ Dtype => refs = d.refs; if(d.ty.kind == Tadt){ for(id = d.ty.ids; id != nil; id = id.next){ d.refs += id.refs; if(id.store != Dfn) continue; if(id.init == nil && id.link == nil && d.importid == nil) error(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not defined"); if(superwarn && !id.refs && d.importid == nil) warn(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not referenced"); } } if(d.ty.kind == Tmodule){ for(id = d.ty.ids; id != nil; id = id.next){ refs += id.refs; if(id.iface != nil) id.iface.refs += id.refs; if(id.store == Dtype){ for(m = id.ty.ids; m != nil; m = m.next){ refs += m.refs; if(m.iface != nil) m.iface.refs += m.refs; } } } d.refs = refs; } if(superwarn && !refs && d.importid == nil) warn(d.src.start, declconv(d)+" not referenced"); Dglobal => if(superwarn && !d.refs && d.sym != nil && d.sym.name[0] != '.') warn(d.src.start, declconv(d)+" not referenced"); Dlocal or Darg => if(!d.refs && d.sym != nil && d.sym.name != nil && d.sym.name[0] != '.') warn(d.src.start, declconv(d)+" not referenced"); Dconst => if(superwarn && !d.refs && d.sym != nil) warn(d.src.start, declconv(d)+" not referenced"); Dfn => if(d.init == nil && d.importid == nil) error(d.src.start, declconv(d)+" not defined"); if(superwarn && !d.refs) warn(d.src.start, declconv(d)+" not referenced"); Dimport => if(superwarn && !d.refs) warn(d.src.start, declconv(d)+" not referenced"); } if(d.das != byte 0) d.refs++; }} vardecl(ids: ref Decl, t: ref Type): ref Node{ n := mkn(Ovardecl, mkn(Oseq, nil, nil), nil); n.decl = ids; n.ty = t; return n;} vardecled(n: ref Node){ store := Dlocal; if(scope == ScopeGlobal) store = Dglobal; if(n.ty.kind == Texception && n.ty.cons == byte 1){ store = Dconst; fatal("Texception in vardecled"); } ids := n.decl; installids(store, ids); t := n.ty; for(last := ids; ids != nil; ids = ids.next){ ids.ty = t; last = ids; } n.left.decl = last;} condecl(ids: ref Decl, init: ref Node): ref Node{ n := mkn(Ocondecl, mkn(Oseq, nil, nil), init); n.decl = ids; return n;} condecled(n: ref Node){ ids := n.decl; installids(Dconst, ids); for(last := ids; ids != nil; ids = ids.next){ ids.ty = tunknown; last = ids; } n.left.decl = last;} exdecl(ids: ref Decl, tids: ref Decl): ref Node{ n: ref Node; t: ref Type; t = mktype(ids.src.start, ids.src.stop, Texception, nil, tids); t.cons = byte 1; n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil); n.decl = ids; n.ty = t; return n;} exdecled(n: ref Node){ ids, last: ref Decl; t: ref Type; ids = n.decl; installids(Dconst, ids); t = n.ty; for(last = ids; ids != nil; ids = ids.next){ ids.ty = t; last = ids; } n.left.decl = last;} importdecl(m: ref Node, ids: ref Decl): ref Node{ n := mkn(Oimport, mkn(Oseq, nil, nil), m); n.decl = ids; return n;} importdecled(n: ref Node){ ids := n.decl; installids(Dimport, ids); for(last := ids; ids != nil; ids = ids.next){ ids.ty = tunknown; last = ids; } n.left.decl = last;} mkscope(body: ref Node): ref Node{ n := mkn(Oscope, nil, body); if(body != nil) n.src = body.src; return n;} fndecl(n: ref Node, t: ref Type, body: ref Node): ref Node{ n = mkbin(Ofunc, n, body); n.ty = t; return n;} fndecled(n: ref Node){ left := n.left; if(left.op == Oname){ d := left.decl.sym.decl; if(d == nil || d.store == Dimport){ d = mkids(left.src, left.decl.sym, n.ty, nil); installids(Dfn, d); } left.decl = d; d.refs++; } if(left.op == Odot) pushscope(nil, Sother); if(n.ty.polys != nil){ pushscope(nil, Sother); installids(Dtype, n.ty.polys); } pushscope(nil, Sother); installids(Darg, n.ty.ids); n.ty.ids = popscope(); if(n.ty.val != nil) mergepolydecs(n.ty); if(n.ty.polys != nil) n.ty.polys = popscope(); if(left.op == Odot) popscope();} ## check the function declaration only# the body will be type checked later by fncheck#fnchk(n: ref Node): ref Decl{ bad := 0; d := n.left.decl; if(n.left.op == Odot) d = n.left.right.decl; if(d == nil) fatal("decl() fnchk nil"); n.left.decl = d; if(d.store == Dglobal || d.store == Dfield) d.store = Dfn; if(d.store != Dfn || d.init != nil){ nerror(n, "redeclaration of function "+dotconv(d)+", previously declared as " +storeconv(d)+" on line "+lineconv(d.src.start)); if(d.store == Dfn && d.init != nil) bad = 1; } d.init = n; t := n.ty; inadt := d.dot; if(inadt != nil && (inadt.store != Dtype || inadt.ty.kind != Tadt)) inadt = nil; if(n.left.op == Odot){ pushscope(nil, Sother); adtp := outerpolys(n.left); if(adtp != nil) installids(Dtype, adtp); if(!polyequal(adtp, n.decl)) nerror(n, "adt polymorphic type mismatch"); n.decl = nil; } t = validtype(t, inadt); if(n.left.op == Odot) popscope(); if(debug['d']) print("declare function %s ty %s newty %s\n", dotconv(d), typeconv(d.ty), typeconv(t)); t = usetype(t); if(!polyequal(d.ty.polys, t.polys)) nerror(n, "function polymorphic type mismatch"); if(!tcompat(d.ty, t, 0)) nerror(n, "type mismatch: "+dotconv(d)+" defined as " +typeconv(t)+" declared as "+typeconv(d.ty)+" on line "+lineconv(d.src.start)); else if(!raisescompat(d.ty.eraises, t.eraises)) nerror(n, "raises mismatch: " + dotconv(d)); if(t.varargs != byte 0) nerror(n, "cannot define functions with a '*' argument, such as "+dotconv(d)); t.eraises = d.ty.eraises; d.ty = t; d.offset = idoffsets(t.ids, MaxTemp, IBY2WD); d.src = n.src; d.locals = nil; n.ty = t; if(bad) return nil; return d;} globalas(dst: ref Node, v: ref Node, valok: int): ref Node{ if(v == nil) return nil; if(v.op == Oas || v.op == Odas){ v = globalas(v.left, v.right, valok); if(v == nil) return nil; }else if(valok && !initable(dst, v, 0)) return nil; case dst.op{ Oname => if(dst.decl.init != nil) nerror(dst, "duplicate assignment to "+expconv(dst)+", previously assigned on line " +lineconv(dst.decl.init.src.start)); if(valok) dst.decl.init = v; return v; Otuple => if(valok && v.op != Otuple) fatal("can't deal with "+nodeconv(v)+" in tuple case of globalas"); tv := v.left; for(dst = dst.left; dst != nil; dst = dst.right){ globalas(dst.left, tv.left, valok); if(valok) tv = tv.right; } return v; } fatal("can't deal with "+nodeconv(dst)+" in globalas"); return nil;} needsstore(d: ref Decl): int{ if(!d.refs) return 0; if(d.importid != nil) return 0; if(storespace[d.store]) return 1; return 0;} ## return the list of all referenced storage variables#vars(d: ref Decl): ref Decl{ while(d != nil && !needsstore(d)) d = d.next; for(v := d; v != nil; v = v.next){ while(v.next != nil){ n := v.next; if(needsstore(n)) break; v.next = n.next; } } return d;} ## declare variables from the left side of a := statement#recdasdecl(n: ref Node, store: int, nid: int): (int, int){ r: int; case n.op{ Otuple => ok := 1; for(n = n.left; n != nil; n = n.right){ (r, nid) = recdasdecl(n.left, store, nid); ok &= r; } return (ok, nid); Oname => if(n.decl == nildecl) return (1, -1); d := mkids(n.src, n.decl.sym, nil, nil); installids(store, d); n.decl = d; old := d.old; if(old != nil && old.store != Dfn && old.store != Dwundef && old.store != Dundef) warn(d.src.start, "redeclaration of "+declconv(d)+", previously declared as " +storeconv(old)+" on line "+lineconv(old.src.start)); d.refs++; d.das = byte 1; if(nid >= 0) nid++; return (1, nid); } return (0, nid);} recmark(n: ref Node, nid: int): int{ case(n.op){ Otuple => for(n = n.left; n != nil; n = n.right) nid = recmark(n.left, nid); Oname => n.decl.nid = byte nid; nid = 0; } return nid;} dasdecl(n: ref Node): int{ ok: int; nid := 0;Lines 1–500 of 1177. Load more
storename := array[Dend] of { Dtype => "type", Dfn => "function", Dglobal => "global", Darg => "argument", Dlocal => "local", Dconst => "con", Dfield => "field", Dtag => "pick tag", Dimport => "import", Dunbound => "unbound", Dundef => "undefined", Dwundef => "undefined", }; storeart := array[Dend] of { Dtype => "a ", Dfn => "a ", Dglobal => "a ", Darg => "an ", Dlocal => "a ", Dconst => "a ", Dfield => "a ", Dtag => "a ", Dimport => "an ", Dunbound => "", Dundef => "", Dwundef => "", }; storespace := array[Dend] of { Dtype => 0, Dfn => 0, Dglobal => 1, Darg => 1, Dlocal => 1, Dconst => 0, Dfield => 1, Dtag => 0, Dimport => 0, Dunbound => 0, Dundef => 0, Dwundef => 0, }; impdecl: ref Decl; impdecls: ref Dlist; scopes := array[MaxScope] of ref Decl; tails := array[MaxScope] of ref Decl; scopekind := array[MaxScope] of byte; scopenode := array[MaxScope] of ref Node; iota: ref Decl; zdecl: Decl; popscopes() { d: ref Decl; # # clear out any decls left in syms # while(scope >= ScopeBuiltin){ for(d = scopes[scope--]; d != nil; d = d.next){ if(d.sym != nil){ d.sym.decl = d.old; d.old = nil; } } } for(id := impdecls; id != nil; id = id.next){ for(d = id.d.ty.ids; d != nil; d = d.next){ d.sym.decl = nil; d.old = nil; } } impdecls = nil; scope = ScopeBuiltin; scopes[ScopeBuiltin] = nil; tails[ScopeBuiltin] = nil; } declstart() { iota = mkids(nosrc, enter("iota", 0), tint, nil); iota.init = mkconst(nosrc, big 0); scope = ScopeNils; scopes[ScopeNils] = nil; tails[ScopeNils] = nil; nildecl = mkdecl(nosrc, Dglobal, tany); nildecl.sym = enter("nil", 0); installids(Dglobal, nildecl); d := mkdecl(nosrc, Dglobal, tstring); d.sym = enterstring(""); installids(Dglobal, d); scope = ScopeGlobal; scopes[ScopeGlobal] = nil; tails[ScopeGlobal] = nil; } redecl(d: ref Decl) { old := d.sym.decl; if(old.store == Dwundef) return; error(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "+storeconv(old)+" on line "+ lineconv(old.src.start)); } checkrefs(d: ref Decl) { id, m: ref Decl; refs: int; for(; d != nil; d = d.next){ if(d.das != byte 0) d.refs--; case d.store{ Dtype => refs = d.refs; if(d.ty.kind == Tadt){ for(id = d.ty.ids; id != nil; id = id.next){ d.refs += id.refs; if(id.store != Dfn) continue; if(id.init == nil && id.link == nil && d.importid == nil) error(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not defined"); if(superwarn && !id.refs && d.importid == nil) warn(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not referenced"); } } if(d.ty.kind == Tmodule){ for(id = d.ty.ids; id != nil; id = id.next){ refs += id.refs; if(id.iface != nil) id.iface.refs += id.refs; if(id.store == Dtype){ for(m = id.ty.ids; m != nil; m = m.next){ refs += m.refs; if(m.iface != nil) m.iface.refs += m.refs; } } } d.refs = refs; } if(superwarn && !refs && d.importid == nil) warn(d.src.start, declconv(d)+" not referenced"); Dglobal => if(superwarn && !d.refs && d.sym != nil && d.sym.name[0] != '.') warn(d.src.start, declconv(d)+" not referenced"); Dlocal or Darg => if(!d.refs && d.sym != nil && d.sym.name != nil && d.sym.name[0] != '.') warn(d.src.start, declconv(d)+" not referenced"); Dconst => if(superwarn && !d.refs && d.sym != nil) warn(d.src.start, declconv(d)+" not referenced"); Dfn => if(d.init == nil && d.importid == nil) error(d.src.start, declconv(d)+" not defined"); if(superwarn && !d.refs) warn(d.src.start, declconv(d)+" not referenced"); Dimport => if(superwarn && !d.refs) warn(d.src.start, declconv(d)+" not referenced"); } if(d.das != byte 0) d.refs++; } } vardecl(ids: ref Decl, t: ref Type): ref Node { n := mkn(Ovardecl, mkn(Oseq, nil, nil), nil); n.decl = ids; n.ty = t; return n; } vardecled(n: ref Node) { store := Dlocal; if(scope == ScopeGlobal) store = Dglobal; if(n.ty.kind == Texception && n.ty.cons == byte 1){ store = Dconst; fatal("Texception in vardecled"); } ids := n.decl; installids(store, ids); t := n.ty; for(last := ids; ids != nil; ids = ids.next){ ids.ty = t; last = ids; } n.left.decl = last; } condecl(ids: ref Decl, init: ref Node): ref Node { n := mkn(Ocondecl, mkn(Oseq, nil, nil), init); n.decl = ids; return n; } condecled(n: ref Node) { ids := n.decl; installids(Dconst, ids); for(last := ids; ids != nil; ids = ids.next){ ids.ty = tunknown; last = ids; } n.left.decl = last; } exdecl(ids: ref Decl, tids: ref Decl): ref Node { n: ref Node; t: ref Type; t = mktype(ids.src.start, ids.src.stop, Texception, nil, tids); t.cons = byte 1; n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil); n.decl = ids; n.ty = t; return n; } exdecled(n: ref Node) { ids, last: ref Decl; t: ref Type; ids = n.decl; installids(Dconst, ids); t = n.ty; for(last = ids; ids != nil; ids = ids.next){ ids.ty = t; last = ids; } n.left.decl = last; } importdecl(m: ref Node, ids: ref Decl): ref Node { n := mkn(Oimport, mkn(Oseq, nil, nil), m); n.decl = ids; return n; } importdecled(n: ref Node) { ids := n.decl; installids(Dimport, ids); for(last := ids; ids != nil; ids = ids.next){ ids.ty = tunknown; last = ids; } n.left.decl = last; } mkscope(body: ref Node): ref Node { n := mkn(Oscope, nil, body); if(body != nil) n.src = body.src; return n; } fndecl(n: ref Node, t: ref Type, body: ref Node): ref Node { n = mkbin(Ofunc, n, body); n.ty = t; return n; } fndecled(n: ref Node) { left := n.left; if(left.op == Oname){ d := left.decl.sym.decl; if(d == nil || d.store == Dimport){ d = mkids(left.src, left.decl.sym, n.ty, nil); installids(Dfn, d); } left.decl = d; d.refs++; } if(left.op == Odot) pushscope(nil, Sother); if(n.ty.polys != nil){ pushscope(nil, Sother); installids(Dtype, n.ty.polys); } pushscope(nil, Sother); installids(Darg, n.ty.ids); n.ty.ids = popscope(); if(n.ty.val != nil) mergepolydecs(n.ty); if(n.ty.polys != nil) n.ty.polys = popscope(); if(left.op == Odot) popscope(); } # # check the function declaration only # the body will be type checked later by fncheck # fnchk(n: ref Node): ref Decl { bad := 0; d := n.left.decl; if(n.left.op == Odot) d = n.left.right.decl; if(d == nil) fatal("decl() fnchk nil"); n.left.decl = d; if(d.store == Dglobal || d.store == Dfield) d.store = Dfn; if(d.store != Dfn || d.init != nil){ nerror(n, "redeclaration of function "+dotconv(d)+", previously declared as " +storeconv(d)+" on line "+lineconv(d.src.start)); if(d.store == Dfn && d.init != nil) bad = 1; } d.init = n; t := n.ty; inadt := d.dot; if(inadt != nil && (inadt.store != Dtype || inadt.ty.kind != Tadt)) inadt = nil; if(n.left.op == Odot){ pushscope(nil, Sother); adtp := outerpolys(n.left); if(adtp != nil) installids(Dtype, adtp); if(!polyequal(adtp, n.decl)) nerror(n, "adt polymorphic type mismatch"); n.decl = nil; } t = validtype(t, inadt); if(n.left.op == Odot) popscope(); if(debug['d']) print("declare function %s ty %s newty %s\n", dotconv(d), typeconv(d.ty), typeconv(t)); t = usetype(t); if(!polyequal(d.ty.polys, t.polys)) nerror(n, "function polymorphic type mismatch"); if(!tcompat(d.ty, t, 0)) nerror(n, "type mismatch: "+dotconv(d)+" defined as " +typeconv(t)+" declared as "+typeconv(d.ty)+" on line "+lineconv(d.src.start)); else if(!raisescompat(d.ty.eraises, t.eraises)) nerror(n, "raises mismatch: " + dotconv(d)); if(t.varargs != byte 0) nerror(n, "cannot define functions with a '*' argument, such as "+dotconv(d)); t.eraises = d.ty.eraises; d.ty = t; d.offset = idoffsets(t.ids, MaxTemp, IBY2WD); d.src = n.src; d.locals = nil; n.ty = t; if(bad) return nil; return d; } globalas(dst: ref Node, v: ref Node, valok: int): ref Node { if(v == nil) return nil; if(v.op == Oas || v.op == Odas){ v = globalas(v.left, v.right, valok); if(v == nil) return nil; }else if(valok && !initable(dst, v, 0)) return nil; case dst.op{ Oname => if(dst.decl.init != nil) nerror(dst, "duplicate assignment to "+expconv(dst)+", previously assigned on line " +lineconv(dst.decl.init.src.start)); if(valok) dst.decl.init = v; return v; Otuple => if(valok && v.op != Otuple) fatal("can't deal with "+nodeconv(v)+" in tuple case of globalas"); tv := v.left; for(dst = dst.left; dst != nil; dst = dst.right){ globalas(dst.left, tv.left, valok); if(valok) tv = tv.right; } return v; } fatal("can't deal with "+nodeconv(dst)+" in globalas"); return nil; } needsstore(d: ref Decl): int { if(!d.refs) return 0; if(d.importid != nil) return 0; if(storespace[d.store]) return 1; return 0; } # # return the list of all referenced storage variables # vars(d: ref Decl): ref Decl { while(d != nil && !needsstore(d)) d = d.next; for(v := d; v != nil; v = v.next){ while(v.next != nil){ n := v.next; if(needsstore(n)) break; v.next = n.next; } } return d; } # # declare variables from the left side of a := statement # recdasdecl(n: ref Node, store: int, nid: int): (int, int) { r: int; case n.op{ Otuple => ok := 1; for(n = n.left; n != nil; n = n.right){ (r, nid) = recdasdecl(n.left, store, nid); ok &= r; } return (ok, nid); Oname => if(n.decl == nildecl) return (1, -1); d := mkids(n.src, n.decl.sym, nil, nil); installids(store, d); n.decl = d; old := d.old; if(old != nil && old.store != Dfn && old.store != Dwundef && old.store != Dundef) warn(d.src.start, "redeclaration of "+declconv(d)+", previously declared as " +storeconv(old)+" on line "+lineconv(old.src.start)); d.refs++; d.das = byte 1; if(nid >= 0) nid++; return (1, nid); } return (0, nid); } recmark(n: ref Node, nid: int): int { case(n.op){ Otuple => for(n = n.left; n != nil; n = n.right) nid = recmark(n.left, nid); Oname => n.decl.nid = byte nid; nid = 0; } return nid; } dasdecl(n: ref Node): int { ok: int; nid := 0;