diff options
Diffstat (limited to 'src/interp')
-rw-r--r-- | src/interp/c-util.boot | 18 | ||||
-rw-r--r-- | src/interp/compiler.boot | 95 | ||||
-rw-r--r-- | src/interp/define.boot | 80 | ||||
-rw-r--r-- | src/interp/g-opt.boot | 26 | ||||
-rw-r--r-- | src/interp/g-util.boot | 23 | ||||
-rw-r--r-- | src/interp/i-syscmd.boot | 2 | ||||
-rw-r--r-- | src/interp/sys-utility.boot | 3 | ||||
-rw-r--r-- | src/interp/wi1.boot | 2 | ||||
-rw-r--r-- | src/interp/wi2.boot | 4 |
9 files changed, 199 insertions, 54 deletions
diff --git a/src/interp/c-util.boot b/src/interp/c-util.boot index 7aba9153..5ccaaa26 100644 --- a/src/interp/c-util.boot +++ b/src/interp/c-util.boot @@ -87,6 +87,12 @@ substituteDollarIfRepHack m == $useRepresentationHack => substitute("$","Rep",m) m +++ Return the triple for the representation domain for the +++ current functor, if any. +getRepresentation: %Env -> %Maybe %Mode +getRepresentation e == + (get("Rep","value",e) or return nil).expr + ++ Returns true if the form `t' is an instance of the Tuple constructor. isTupleInstance: %Form -> %Boolean @@ -1103,13 +1109,19 @@ proclaimCapsuleFunction(op,sig) == ["FUNCTION",[:[vmType first d for d in tails rest sig],"%Shell"], vmType first sig],op]] where vmType d == - getVMType normalize(d,true) - normalize(d,top?) == + $subdomain and d = "$" => + -- We want accurate approximation for subdomains/superdomains + -- that are specialized and known to the VM. + (m := getVMType normalize $functorForm) = "%Thing" => + getVMType normalize $ + m + getVMType normalize d + normalize(d,top? == true) == d = "$" => not top? => "*" -- If the representation is explicitly stated, use it. That way -- we optimize abstractions just as well as builtins. - r := get("Rep","value",$e) => normalize(r.expr,top?) + r := getRepresentation $e => normalize(r,top?) -- Cope with old-style constructor definition atom $functorForm => [$functorForm] normalize($functorForm,top?) diff --git a/src/interp/compiler.boot b/src/interp/compiler.boot index b49a420c..ad1392fe 100644 --- a/src/interp/compiler.boot +++ b/src/interp/compiler.boot @@ -803,6 +803,7 @@ setqSetelt([v,:s],val,m,E) == comp(["setelt",v,:s,val],m,E) setqSingle(id,val,m,E) == + checkVariableName id $insideSetqSingleIfTrue: local:= true --used for comping domain forms within functions currentProplist:= getProplist(id,E) @@ -1451,17 +1452,39 @@ coerceEasy(T,m) == T.mode=$EmptyMode or modeEqualSubst(T.mode,m,T.env) => [T.expr,m,T.env] +++ Return true if the VM constant form `val' is known to satisfy +++ the predicate `pred'. Note that this is a fairly conservatism +++ approximation in the sense that the retunred value maye be false +++ for some other reasons, such as the predicate not being closed +++ with respect to the parameter `#1'. satisfies(val,pred) == pred=false or pred=true => pred + vars := findVMFreeVars pred + vars ^= nil and vars isnt ["#1"] => false eval ["LET",[["#1",val]],pred] + +++ If the domain designated by the domain forms `m' and `m'' have +++ a common super domain, return least such super domaon (ordered +++ in terms of sub-domain relationship). Otherwise, return nil. +commonSuperType(m,m') == + lineage := [m'] + while (t := superType m') ^= nil repeat + lineage := [t,:lineage] + m' := t + while m ^= nil repeat + member(m,lineage) => return m + m := superType m + +++ Coerce value `x' of mode `m' to mode `m'', if m is a subset of +++ of m'. A special case is made for cross-subdomain conversion +++ for integral literals. coerceSubset: (%Triple,%Mode) -> %Maybe %Triple coerceSubset([x,m,e],m') == isSubset(m,m',e) => [x,m',e] - isDomainForm(m,e) and isSubDomain(m,m') => [x,m',e] - INTEGERP x => + INTEGERP x and (m'' := commonSuperType(m,m')) => -- obviously this is temporary - satisfies(x,isSubDomain(m',maximalSuperType m)) => [x,m',e] + satisfies(x,isSubDomain(m',m'')) => [x,m',e] nil nil @@ -1539,6 +1562,30 @@ compCoerce(["::",x,m'],m,e) == T:= (or/[compCoerce1(x,m1,e) for m1 in l]) or return nil coerce([T.expr,m',T.env],m) +++ Subroutine of compCoerce1. If `T' is a triple whose mode is +++ a super-domain of `sub', then return code that performs the +++ checked courtesy coercion to `sub'. +coerceSuperset: (%Triple, %Mode) -> %Maybe %Triple +coerceSuperset(T,sub) == + sub = "$" => + T' := coerceSuperset(T,$functorForm) or return nil + rplac(second T',"$") + T' + pred := isSubset(sub,T.mode,T.env) => + -- Don't bother introducing a temporary if we have an + -- atomic expression. + simple? := atom T.expr and not MEMQ(T.expr,$functorLocalParameters) + g := + simple? => T.expr + GENSYM() + result := + simple? => g + ["%LET",g,T.expr] + pred := substitute(g,"#1",pred) + code := ["PROG1",result, ["check-subtype",pred,MKQ sub,g]] + [code,sub,T.env] + nil + compCoerce1(x,m',e) == T:= comp(x,m',e) or comp(x,$EmptyMode,e) or return nil m1:= @@ -1548,11 +1595,8 @@ compCoerce1(x,m',e) == T:=[T.expr,m1,T.env] T':= coerce(T,m') => T' T':= coerceByModemap(T,m') => T' - pred := isSubset(m',T.mode,e) => - gg := GENSYM() - pred := substitute(gg,"#1",pred) - code := ['PROG1,["%LET",gg,T.expr], ['check_-subtype,pred,MKQ m',gg]] - [code,m',T.env] + T' := coerceSuperset(T,m') => T' + nil coerceByModemap([x,m,e],m') == --+ modified 6/27 for new runtime system @@ -1994,7 +2038,9 @@ listOrVectorElementMode x == x is [a,b,:.] and member(a,'(PrimitiveArray Vector List)) => b compIterator(it,e) == + -- ??? Allow for declared iterator variable. it is ["IN",x,y] => + checkVariableName x --these two lines must be in this order, to get "for f in list f" --to give an error message if f is undefined [y',m,e]:= comp(y,$EmptyMode,e) or return nil @@ -2008,6 +2054,7 @@ compIterator(it,e) == [y'',m'',e] := coerce([y',m,e], mOver) or return nil [["IN",x,y''],e] it is ["ON",x,y] => + checkVariableName x $formalArgList:= [x,:$formalArgList] [y',m,e]:= comp(y,$EmptyMode,e) or return nil [mOver,mUnder]:= @@ -2019,6 +2066,7 @@ compIterator(it,e) == [y'',m'',e] := coerce([y',m,e], mOver) or return nil [["ON",x,y''],e] it is ["STEP",index,start,inc,:optFinal] => + checkVariableName index $formalArgList:= [index,:$formalArgList] --if all start/inc/end compile as small integers, then loop --is compiled as a small integer loop @@ -2148,7 +2196,34 @@ exprDifference(x,y) == y=0 => x FIXP x and FIXP y => DIFFERENCE(x,y) ["DIFFERENCE",x,y] - + + +--% rep/per morphisms + +++ Compile the form `per x' under the mode `m'. +++ The `per' operator is active only for new-style definition for +++ representation domain. +compPer(["per",x],m,e) == + $useRepresentationHack => nil + inType := getRepresentation e or return nil + T := comp(x,inType,e) or return nil + if $subdomain then + T := + INTEGERP T.expr and satisfies(T.expr,domainVMPredicate "$") => + [T.expr,"$",e] + coerceSuperset(T,"$") or return nil + else + rplac(second T,"$") + coerce(T,m) + +++ Compile the form `rep x' under the mode `m'. +++ Like `per', the `rep' operator is active only for new-style +++ definition for representation domain. +compRep(["rep",x],m,e) == + $useRepresentationHack => nil + T := comp(x,"$",e) or return nil + rplac(second T,getRepresentation e or return nil) + coerce(T,m) --% --% Entry point to the compiler @@ -2231,6 +2306,8 @@ for x in [["|", :"compSuchthat"],_ ["Mapping", :"compCat"],_ ["UnionCategory", :"compConstructorCategory"],_ ["where", :"compWhere"],_ + ["per",:"compPer"],_ + ["rep",:"compRep"],_ ["%Comma",:"compComma"],_ ["%Match",:"compMatch"],_ ["[||]", :"compileQuasiquote"]] repeat diff --git a/src/interp/define.boot b/src/interp/define.boot index a026ed33..e3dc8934 100644 --- a/src/interp/define.boot +++ b/src/interp/define.boot @@ -106,13 +106,27 @@ $sigList := [] $atList := [] +++ True if the current functor definition refines a domain. +$subdomain := false + --% compDefineAddSignature: (%Form,%Signature,%Env) -> %Env DomainSubstitutionFunction: (%List,%Form) -> %Form ---% +--% Subdomains + +++ We are defining a functor with head given by `form', as a subdomain +++ of the domain designated by the domain form `super', and predicate +++ `pred' (a VM instruction form). Emit appropriate info into the +++ databases. +emitSubdomainInfo(form,super,pred) == + pred := eqSubst($AtVariables,rest form,pred) + super := eqSubst($AtVariables,rest form,super) + evalAndRwriteLispForm("evalOnLoad2",["noteSubDomainInfo", + quoteForm first form,quoteForm super, quoteForm pred]) + ++ List of operations defined in a given capsule ++ Each item on this list is of the form @@ -161,21 +175,23 @@ makePredicate l == --% FUNCTIONS WHICH MUNCH ON == STATEMENTS +++ List of reserved identifiers for which the compiler has special +++ meanings and that shall not be redefined. +$reservedNames == '(per rep _$) + +++ Check that `var' (a variable of parameter name) is not a reversed name. +checkVariableName var == + MEMQ(var,$reservedNames) => + stackAndThrow('"You cannot reserved name %1b as variable",[var]) + +checkParameterNames parms == + for p in parms repeat + checkVariableName p + compDefine(form,m,e) == $macroIfTrue: local := false compDefine1(form,m,e) -++ Activate synthetized pair concretization and abstraction -++ view morphisms for domains. -insertViewMorphisms: (%Mode,$Env) -> %Env -insertViewMorphisms(t,e) == - $useRepresentationHack => e - g := GENSYM() - repType := ["Mapping",t,"$"] - perType := ["Mapping","$",t] - e := put("rep","value",[["XLAM",[g],g],repType,nil],e) - put("per","value",[["XLAM",[g],g],perType,nil],e) - ++ We are about to process the body of a capsule. Check the form of ++ `Rep' definition, and whether it is appropriate to activate the ++ implicitly generated morphisms @@ -238,13 +254,15 @@ checkRepresentation(addForm,body,env) == else if null domainRep and addForm ^= nil then if $functorKind = "domain" and addForm isnt ["%Comma",:.] then domainRep := - addForm is ["SubDomain",dom,.] => dom + addForm is ["SubDomain",dom,.] => + $subdomain := true + dom addForm base := compForMode(domainRep,$EmptyMode,env) or stackAndThrow('"1b is not a domain",[domainRep]) $useRepresentationHack := false - env := insertViewMorphisms(base.expr,env) - -- ??? Maybe we should also make Rep available as macro. + env := put("Rep","value",base,env) + -- ??? Maybe we should also make Rep available as macro? env @@ -254,7 +272,8 @@ compDefine1(form,m,e) == --1. decompose after macro-expanding form ['DEF,lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e) $insideWhereIfTrue and isMacro(form,e) and (m=$EmptyMode or m=$NoValueMode) - => [lhs,m,put(first lhs,'macro,rhs,e)] + => [lhs,m,put(first lhs,"macro",rhs,e)] + checkParameterNames rest lhs null signature.target and not MEMQ(KAR rhs,$BuiltinConstructorNames) and (sig:= getSignatureFromMode(lhs,e)) => -- here signature of lhs is determined by a previous declaration @@ -339,7 +358,9 @@ macroExpandInPlace(x,e) == macroExpand: (%Form,%Env) -> %Form macroExpand(x,e) == --not worked out yet - atom x => (u:= get(x,'macro,e) => macroExpand(u,e); x) + atom x => + u:= get(x,"macro",e) => macroExpand(u,e) + x x is ['DEF,lhs,sig,spCases,rhs] => ['DEF,macroExpand(lhs,e),macroExpandList(sig,e),macroExpandList(spCases,e), macroExpand(rhs,e)] @@ -348,7 +369,7 @@ macroExpand(x,e) == --not worked out yet macroExpandList(l,e) == -- macros should override niladic props (l is [name]) and IDENTP name and niladicConstructorFromDB name and - (u := get(name, 'macro, e)) => macroExpand(u,e) + (u := get(name,"macro", e)) => macroExpand(u,e) [macroExpand(x,e) for x in l] --% constructor evaluation @@ -580,6 +601,7 @@ compDefineFunctor1(df is ['DEF,form,signature,$functorSpecialCases,body], [lineNumber,:$functorSpecialCases] := $functorSpecialCases -- 1. bind global variables $addForm: local := nil + $subdomain: local := false $viewNames: local:= nil --This list is only used in genDomainViewName, for generating names @@ -666,6 +688,14 @@ compDefineFunctor1(df is ['DEF,form,signature,$functorSpecialCases,body], -- 4. compile body in environment of %type declarations for arguments op':= $op rettype:= signature'.target + -- If this functor is defined as instantiation of a functor + -- that is a subdomain of `D', then make this functor also a subdomain + -- of that super domain `D'. + if body is ["add",[rhsCtor,:rhsArgs],["CAPSULE"]] + and constructor? rhsCtor + and (u := getSuperDomainFromDB rhsCtor) then + u := sublisFormal(rhsArgs,u,$AtVariables) + emitSubdomainInfo($form,first u, second u) T:= compFunctorBody(body,rettype,$e,parForm) -- If only compiling certain items, then ignore the body shell. $compileOnlyCertainItems => @@ -1445,12 +1475,8 @@ compSubDomain1(domainForm,predicate,m,e) == -- For now, reject predicates that directly reference domains CONTAINED("$",pred) => stackAndThrow('"predicate %1pb is not simple enough",[predicate]) - -- Abstract over references to parameters of enclosing functor. - pred := eqSubst($AtVariables,rest $form, pred) - $lisplibSuperDomain:= - [domainForm,predicate] - evalAndRwriteLispForm('evalOnLoad2, ["noteSubDomainInfo", quoteForm $op, - quoteForm domainForm, quoteForm pred]) + emitSubdomainInfo($form,domainForm,pred) + $lisplibSuperDomain := [domainForm,predicate] [domainForm,m,e] compCapsuleInner(itemList,m,e) == @@ -1516,10 +1542,8 @@ doIt(item,$predl) == $functorLocalParameters:= [:$functorLocalParameters,lhs] if code is ["%LET",.,rhs',:.] and isDomainForm(rhs',$e) then if lhs="Rep" then - $Representation:= (get("Rep",'value,$e)).expr + $Representation:= getRepresentation $e --$Representation bound by compDefineFunctor, used in compNoStacking - -- Activate view morphisms if appropriate - $e := insertViewMorphisms($Representation,$e) code is ["%LET",:.] => RPLACA(item,"setShellEntry") rhsCode := rhs' @@ -1537,7 +1561,7 @@ doIt(item,$predl) == item is ["where",b,:l] => compOrCroak(item,$EmptyMode,$e) item is ["MDEF",:.] => [.,.,$e]:= compOrCroak(item,$EmptyMode,$e) item is ['DEF,[op,:.],:.] => - body:= isMacro(item,$e) => $e:= put(op,'macro,body,$e) + body:= isMacro(item,$e) => $e:= put(op,"macro",body,$e) [.,.,$e]:= t:= compOrCroak(item,$EmptyMode,$e) RPLACA(item,"CodeDefine") --Note that DescendCode, in CodeDefine, is looking for this diff --git a/src/interp/g-opt.boot b/src/interp/g-opt.boot index 49c0229a..4a0a91af 100644 --- a/src/interp/g-opt.boot +++ b/src/interp/g-opt.boot @@ -374,8 +374,9 @@ optLESSP u == $simpleVMoperators == '(CONS CAR CDR LENGTH SIZE EQUAL EQL EQ NOT NULL OR AND - SPADfirst QVELT _+ _- _* _< _= - QEQCAR QCDR QCAR INTEGERP FLOATP STRINGP IDENTP SYMBOLP) + SPADfirst QVELT _+ _- _* _< _= ASH INTEGER_-LENGTH + QEQCAR QCDR QCAR INTEGERP FLOATP STRINGP IDENTP SYMBOLP + MINUSP GREATERP) isSimpleVMForm form == isAtomicForm form => true @@ -392,6 +393,27 @@ isFloatableVMForm form == "and"/[isFloatableVMForm arg for arg in rest form] +++ Return true if the VM form `form' is one that we certify to +++ evaluate to a (compile time) constant. Note that this is a +++ fairly conservative approximation of compile time constants. +isVMConstantForm: %Code -> %Boolean +isVMConstantForm form == + INTEGERP form or STRINGP form => true + form=nil or form=true => true + form isnt [op,:args] => false + op = "QUOTE" => true + MEMQ(op,$simpleVMoperators) and + "and"/[isVMConstantForm arg for arg in args] + +++ Return the set of free variables in the VM form `form'. +findVMFreeVars form == + IDENTP form => [form] + form isnt [op,:args] => nil + op = "QUOTE" => nil + vars := union/[findVMFreeVars arg for arg in args] + atom op => vars + union(findVMFreeVars op,vars) + ++ Implement simple-minded LET-inlining. It seems we can't count ++ on Lisp implementations to do this simple transformation. ++ This transformation will probably be more effective when all diff --git a/src/interp/g-util.boot b/src/interp/g-util.boot index 7889e49f..8826bd95 100644 --- a/src/interp/g-util.boot +++ b/src/interp/g-util.boot @@ -74,6 +74,14 @@ superType dom == [super,.] := getSuperDomainFromDB ctor or return nil sublisFormal(args,super,$AtVariables) +++ If the domain designated by the domain form `dom' is a subdomain, +++ then return its defining predicate. Otherwise, return nil. +domainVMPredicate dom == + dom = "$" => domainVMPredicate $functorForm + dom isnt [ctor,:args] => false + [.,pred] := getSuperDomainFromDB ctor or return nil + sublisFormal(args,pred,$AtVariables) + ++ Return the root of the reflexive transitive closure of ++ the super-domain chain for the domain designated by the domain ++ form `d'. @@ -104,15 +112,16 @@ isSubDomain(d1,d2) == [sup,pred] := getSuperDomainFromDB first d1 or return false -- 3. We may be onto something. - -- `sup' and `pred' are in most general form. Instantiate. - first sup = first d2 => - -- sanity check. `d2' should be an instance of `sup'. - sublisFormal(rest d1,sup,$AtVariables) ^= d2 => - stackAndThrow('"unexpected instantiation mismatch",nil) - sublisFormal(rest d1,pred,$AtVariables) + -- `sup' and `pred' are in most general form. We cannot just + -- test for the functors, as different arguments may instantiate + -- to super-domains. + args := rest d1 + sublisFormal(args,sup,$AtVariables) = d2 => + sublisFormal(args,pred,$AtVariables) -- 4. Otherwise, lookup in the super-domain chain. - pred' := isSubDomain(sup,d2) => MKPF([pred',pred],"AND") + pred' := isSubDomain(sup,d2) => + MKPF([pred',sublisFormal(args,pred,$AtVariables)],"AND") -- 5. Lot of smoke, no fire. false diff --git a/src/interp/i-syscmd.boot b/src/interp/i-syscmd.boot index d0386605..a64c0d97 100644 --- a/src/interp/i-syscmd.boot +++ b/src/interp/i-syscmd.boot @@ -1033,7 +1033,7 @@ displaySpad2Cmd l == v option = 'operations => displayOperations vl - option = 'macros => displayMacros vl + option = "macros" => displayMacros vl option = 'names => displayWorkspaceNames() displayProperties(option,l) optList:= [:['%l,'" ",x] for x in $displayOptions] diff --git a/src/interp/sys-utility.boot b/src/interp/sys-utility.boot index fa924cb9..d34cc4b8 100644 --- a/src/interp/sys-utility.boot +++ b/src/interp/sys-utility.boot @@ -1,4 +1,4 @@ --- Copyright (C) 2007-2008 Gabriel Dos Reis. +-- Copyright (C) 2007-2009 Gabriel Dos Reis. -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without @@ -71,6 +71,7 @@ getVMType d == Record => #rest d' > 2 => "%Shell" "%Pair" + IndexedList => "%List" otherwise => "%Thing" -- good enough, for now. --% diff --git a/src/interp/wi1.boot b/src/interp/wi1.boot index 54f9f744..718b413c 100644 --- a/src/interp/wi1.boot +++ b/src/interp/wi1.boot @@ -1079,7 +1079,7 @@ compDefine1(form,m,e) == --1. decompose after macro-expanding form ['DEF,lhs,signature,specialCases,rhs]:= form:= macroExpand(form,e) $insideWhereIfTrue and isMacro(form,e) and (m=$EmptyMode or m=$NoValueMode) - => [lhs,m,put(first lhs,'macro,rhs,e)] + => [lhs,m,put(first lhs,"macro",rhs,e)] null signature.target and not MEMQ(KAR rhs,$BuiltinConstructorNames) and (sig:= getSignatureFromMode(lhs,e)) => -- here signature of lhs is determined by a previous declaration diff --git a/src/interp/wi2.boot b/src/interp/wi2.boot index a7c951ca..5b8a57cb 100644 --- a/src/interp/wi2.boot +++ b/src/interp/wi2.boot @@ -411,7 +411,7 @@ compMakeCategoryObject(c,$e) == nil macroExpand(x,e) == --not worked out yet - atom x => (u:= get(x,'macro,e) => macroExpand(u,e); x) + atom x => (u:= get(x,"macro",e) => macroExpand(u,e); x) x is ['DEF,lhs,sig,spCases,rhs] => ['DEF,macroExpand(lhs,e), macroExpandList(sig,e),macroExpandList(spCases,e), macroExpand(rhs,e)] @@ -1140,7 +1140,7 @@ rhsOfLetIsDomainForm code == doItDef item == ['DEF,[op,:.],:.] := item - body:= isMacro(item,$e) => $e:= put(op,'macro,body,$e) + body:= isMacro(item,$e) => $e:= put(op,"macro",body,$e) [.,.,$e]:= t:= compOrCroak(item,$EmptyMode,$e) chk(item,3) RPLACA(item,"CodeDefine") |