aboutsummaryrefslogtreecommitdiff
path: root/src/interp
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp')
-rw-r--r--src/interp/c-util.boot18
-rw-r--r--src/interp/compiler.boot95
-rw-r--r--src/interp/define.boot80
-rw-r--r--src/interp/g-opt.boot26
-rw-r--r--src/interp/g-util.boot23
-rw-r--r--src/interp/i-syscmd.boot2
-rw-r--r--src/interp/sys-utility.boot3
-rw-r--r--src/interp/wi1.boot2
-rw-r--r--src/interp/wi2.boot4
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")