没有合适的资源?快使用搜索试试~ 我知道了~
可在www.sciencedirect.com在线获取理论计算机科学电子笔记312(2015)197-213www.elsevier.com/locate/entcsSkalpel:一个标准MLVincent Rahli康奈尔大学伊萨卡分校Joe Wells,John Pirie和Fairouz Kamareddine爱丁堡赫瑞瓦特大学摘要具有类型推断算法的语言的编译器产生令人困惑的类型错误消息,并且给出通常远离类型错误的真实位置的单个错误位置。 尝试解决这个问题1)未能包括构成类型错误的多个程序点,2)经常报告不对应于用户程序中的任何位置的树片段,以及3)给出可能是高度混淆的不正确的类型信息/诊断。 我们提出了Skalpel,类型错误切片工具,通过只给程序员提供与类型错误有关的所有信息来解决这些问题以显著帮助诊断和修复类型错误。Skalpel由一个复杂的新的约束生成器,这是线性的大小和一个新的约束求解器,这是终止。保留字:自动类型推断,自动错误诊断,改进的 错误报告。1导言相关工作像SML、Haskell和OCaml这样的编程语言依赖于允许自动类型推断的类型系统,使程序员从显式编写类型中解放出来。这些类型推断算法允许在早期阶段(编译时)检测编程错误不幸的是,这些编译器给出了混乱的类型错误报告,浪费了用户我们提出了Skalpel,类型错误切片工具,它可以帮助程序员隔离正是一个病态类型的程序的部分(片)的错误。生成的切片包含所有且仅包含与错误相关的程序部分标准ML的原始类型检查算法是算法W [3],当统一失败时,它会归咎于单个抽象语法树节点。已经开发了该算法的变体,例如M [10]和W然而,所有这些算法仍然归咎于单个节点,http://dx.doi.org/10.1016/j.entcs.2015.04.0121571-0661/© 2015作者。出版社:Elsevier B.V.这是一篇基于CC BY-NC-ND许可证的开放获取文章(http://creativecommons.org/licenses/by-nc-nd/4.0/)。198诉Rahli等人/理论计算机科学电子笔记312(2015)197由多个错误位置组成的错误的抽象语法树。此外,现有编译器报告的错误令人困惑,因为它们经常给出不正确的类型信息/诊断,并报告与用户程序不对应的抽象语法树自动发现编程语言中的类型错误是一项艰巨的任务。成功的尝试需要解决约束系统(使用基于约束的方法来定位错误的系统,与使用基于替换的方法的编译器不同),但这些系统仅在[8]和[5]中为类似玩具的语言构建。在[14]中采用了一种更有前途的方法,但是用于证明关键思想的语言的支持部分仍然很小。此外,解决不良类型错误报告的现有提议(例如,[2]、[6]和[13])简单地重复调用编译器,并在不可键入的程序中删除/添加回部分,以缩小错误点。查找类型错误和报告可能的解决方案的问题是非常困难的,自动解决它甚至更困难。程序中的每一条语法都必须自动标记,约束需要自动生成和求解,而寻找解决方案可能会导致新的约束和组合约束大小爆炸。我们开发了一种新的方法和工具(Skalpel),解决了上述问题。Skalpel将程序点(标签)附加到生成的约束上,这样当统一失败时,我们可以报告归因于生成的约束的标签,给出错误的完整描述。我们annotate约束与这些标签来描述什么样的一组程序点的约束是涉及。当Skalpel被要求检查程序的类型错误时,它会运行其复杂的约束生成器/求解器(大小和终止都是线性的)。如果求解约束失败(即,如果代码中有错误),Skalpel必须自动决定程序的哪些部分(切片)对错误负责然后,Skalpel生成一个类型错误切片,突出显示代码中导致类型错误的最小信息量。通过查看高亮显示的区域,用户可以确信类型错误可以在其中一个高亮显示的位置中得到修复,并且非高亮显示的位置不会导致任何错误。我们的贡献包括:• 与其他使用替代方法求解的算法不同,例如M [10]和W• Skalpel将显示导致错误的所有程序位置• Skalpel足够通用,不仅可以处理包含单个类型错误的源代码的一个文件,而且我们传递给用户的类型错误切片可能涉及多个源代码文件,并且在所有的类型错误文件中都会突出显示。此外,如果提供给Skalpel的源代码包含多个单独的类型错误,Skalpel会产生所有的罪魁祸首多个程序切片。• 约束生成器在程序和约束的大小上是线性的诉Rahli等人/理论计算机科学电子笔记312(2015)197199QQQQ <$Q <$Q<$Q <$Q<$QL解算器终止(引理3.1和3.3)。• Skalpel是第一次尝试使用约束方法来处理整个编程语言,本文给出了其核心在第2节中,我们讨论使用的基本符号第三部分介绍了Skalpel的技术核心。特别是,我们讨论了我们的新的约束表示,这是至关重要的,我们克服了约束大小爆炸的挑战时,处理整个编程语言,如SML。我们表明,约束生成是线性的,约束求解终止。我们在第4节结束。2数学符号设i,j,m,n,p,q在自然数集合N上的范围如果v的范围在类C上,则vx(其中x可以是任何值)和vJ,vJJ,等等,范围也超过C。让我们在集合上范围。如果v在s上的范围,则令v在P(s)上的范围,即s的幂集。让dj(s1, . ,Sn)(“disjoin t”)保持i ∈ { 1,. ,n},ifi j则sisj=0。Let如果dj(s1,s2),则s1s2是s1≠ s2,否则定义为。设x,y是x和y的对。 如果rel是一个二元关系(一个对集),令(x rel y)i <$x,y ∈ rel,令rel的逆rel −1定义为{x,y |y,x ∈ rel},令dom(rel)={x|很好x,y ∈ rel},令ran(rel)={y|你好x,y∈rel},令sa rel ={x,y∈rel|x∈s},令s d rel ={x,y∈rel|x/∈s}。设f在函数上值域(二元关系的一种特殊情况),令s→SJ={f|dom(f)sran(f)sJ},并让x<$→y是在编写某些函数时使用的x,y的替代符号。元组t是一个函数,使得dom(t)<$N,如果1≤j∈dom(t),则j−1 ∈ dom(t)。让t的范围超过元组。 如果v范围超过vers,则令−→v范围超过ver元组={t|run(t)s}。我们写元组{0 <$→x0,.,n<$→x n}为nx0,...,x n= 0。设@ append元组:x1, . ,xi ,yj=1, . ,xi,yi,. ,yj. Givennnsetss1, . ,sn,让s1,...,s n是{nx1,...,x n|i∈ {1,.,n}.x i∈s i}. 请注意,s1,…s n元组(s1<$· ·<$s n)。对于某些约化关系R,我们将其自反闭包和传递闭包记为R。3Skalpel的技术核心我们将本节中定义的系统称为Skalpel核心,包括本节中定义的约束生成器和求解器我们首先介绍图1中给出的外部标记语法,它描述了SML语言的一个子集,选择它来表达核心思想。[1]大多数句法形式都有标签(l),生成标签是为了跟踪错误的责任。 我们1我们不强制执行SML语法的所有语法限制,例如:在val recpat=exp中,表达式exp必须是一个fn-表达式(在本文中我们不强制使用)。200诉Rahli等人/理论计算机科学电子笔记312(2015)197将一些术语(如函数应用)用括号括起来|以便为标签提供视觉上方便的位置。图 1外部标记语法:Skalpel处理的SML子集l∈Label(labels)PL∈ExtLabSynt(Union of below sets)tv∈ TyVar(类型变量)tc∈ TyCon(类型构造函数)strid∈ StrId(结构标识符)vvar∈ ValVar(值变量)dcon∈ DatCon(数据类型构造函数)vid∈VId::=vvar|dconltc∈LabTyCon::=tc lldcon∈LabDatCon::= dconldn∈DatName::=[tv tc|Latpat∈ AtPat::=vidlL数据类型dn=cb斯特尔代茨|Strexp我们将在本文中给出一个运行示例。我们将使用的SML程序作为示例如下所示。我们在这里提出这一点是为了展示如何用标签注释语法fn yl2letl3valrecfl8 =17 fnxl9 L10xl12yl13|l11in[fl4yl5|l6端[在图1中,值标识符(vid)被下标为表达式(vidl)、数据类型构造函数定义(dconl)和模式(vidl)的消歧规则。电子商务货币。无歧义(因此无下标)值标识符出现在模式和数据类型声明中的一元位置。虽然SML通过类型系统中的as- signing状态来区分值变量和数据类型构造函数,但我们通过定义两个不相交的集合ValVar和DatCon来区分它们。与Skalpel核心相反,为了完全正确的最小错误切片,[12]的第14.1节处理标识符状态。此外,为了简化本文中Skalpel核心的介绍,数据库被限制为一个构造函数和一个类型参数。3.1约束语法在本节中,我们在图2中给出了Skalpel核心的约束语法。这种语法用于表示约束,例如在约束生成器中,我们构建约束,这些约束将用于确定程序是否是可键入的或错误的(第3.2节),并在约束求解器(第3.3节)定位错误。第3.1.1节. 3.1.3解释此语法的各个部分的动机pLCB∈ConBind::= dcon l|lty的dconC阿特普∈AtExp::= vid l|让l在expend中下降e专利∈专利::= atpat| [ldcon atpat|实验室Ty∈TyL::= tv l|ty1→ty2| [泰和电讯有限公司|L斯特尔代茨∈StrDecL* =dec|结构strid = strexpStrexp∈StrExp::=斯特里德湖|structlstrdec1···strdecnendDec∈Dec::= val recpatl exp |da|da=exp∈ExpL::= atexp|fnpatexpr| [exp atexp|LID∈ID::= vid|strid|电视|TCterm∈Term* =ltc|ldcon|Ty|CB|DN|exp|专利|诉Rahli等人/理论计算机科学电子笔记312(2015)197201↓ ↓ ↓↓† † ††在初始约束生成或约束求解过程中,构建避免重复的环境。 请注意,早期的系统(例如[4])对表示模块系统的限制太大,因为它们只支持我们绑定器的非常有限的情况。有了我们的约束,我们可以很容易地定义一个组合约束生成算法。图2约束条件CL∈ IntLabSynt(Union of below sets andLabel)ev∈ EnvVar(环境变量)δ∈ TyConVar(类型构造器变量)μ∈ITyCon::=δ|γ|arr| μ,lτ∈ITy::=α |τ μ |τ1⭢ τ2|⟨τ,l ⟩γ∈ TyConName(类型构造函数名称)α∈ ITyVar(内部类型变量)tcs∈ ITyConScheme::=v.μes∈EnvScheme::=v. ets∈ITyScheme::= μ v.τc ∈ EqCs::= μ1= μ2|e 1= e 2|τ1= τ2bind∈Bind::=tc=tcs|strid=es|tv=ts| vid=ts acc∈访问器::=tc=δ|strid=ev|tv=α|vid =αe∈Env::=T|EV|结合|ACC|C|聚乙烯|你好e|电子2,电子1|塞韦湖额外元变量ct∈CsTerm::= τ|μ|eσ∈Scheme::= ts|TCS|esv∈Var::= α|δ| eva∈Atom::= v|γ|Ldep∈ Dependent::=ct,l在分析期间,依赖形式<$CL,l<$取决于具有l中的标签的程序节点,例如,依赖等式约束<$τ1= τ2,l<${l}<$可能针对带标签的函数应用程序<$expatexp生成|l,指示等式约束τ1= τ2仅在节点l尚未被切出的情况下才需要为真。为了操作我们的标签,我们在下面定义了两个函数strip和collapse,它们分别允许我们获取任何给定项的所有标签,以及联合项的嵌套标签。注意dom(strip)=dom(collapse )=IntLabSynt , ran ( strip ) 是 任 何 不 是 依 赖 形 式 的 语 法 , 而 ran ( collapse )=IntLabSynt。.strip(y)ifCL=y,l⎧⎪⎨collapse(⟨y,l∪lJ⟩)C条带(CL)=CL否则塌陷(L)=⎪⎩如果CL=l(lj,lj),lJ,CL否则请注意,我们有时会把ct,l写成ct,{l}。给定一个标签或一组标签y,我们写cty来表示y,且ct1=ct 2第1 =CT2,y= 0.3.1.1内部类型(τ)及其构造函数(μ)ITy和ITyCon集合包含内部类型和内部类型构造函数.为了保持核心的简单性,只支持一元类型构造函数。2我们有一种特殊的类型构造函数,它用于在一元类型构造函数和箭头(→)类型之间的约束求解过程中创建约束。2[12]中的14.10节提出了一个解决方案,使类型构造函数可以具有任何arity。202诉Rahli等人/理论计算机科学电子笔记312(2015)197↓↓††↓†y↓↓3.1.2方案(σ)有三种普遍量化的方案:类型方案(类似于[9]中的方案),类型构造器方案和环境方案。 所有方案都要经过α转换(例如,方案α1.α1和α2。α2是等价的)。3.1.3约束/环境形式(e)形式e应该被看作是一种约束和一种环境。这种形式可以是以下任何一种(i) 空的环境/满足的约束。 这表示为≤。(ii) 环境变量。我们写[e]来表示(ev.ev=e),其中ev不出现在e中。这是一个约束,它强制执行e的逻辑约束性质,同时限制其绑定的范围。请注意,如果e约束环境变量,则绑定仍然可以具有e(iii) 一个合成环境。我们使用运算符注意e;≤,≤;e,和e是等价的。(iv) 活页夹/附件。 绑定器的形式为id=σ,访问器的形式为id=v。绑定器表示正在绑定的标识符id的程序出现,访问器表示使用该绑定的位置,例如,在环境vid=x;vid=α中,内部类型变量α通过vid的绑定被约束为x的实例。在这种情况下,我们说binder和vid的accessor是连接的。此外,活页夹和附件通常可以在不彼此相邻的情况下连接,在环境vid = x;. ;vid=α可能vid的绑定器和访问器连接。有一些环境形式可以在省略(.)这意味着访问器和活页夹将断开连接。第3.1.5节描述了阴影,具体说明了哪些形式会导致这种情况。- 是的CT通过 vid=ct并替换依赖形式我们讨论↓vid=↓x= ct,y x vid=ct.访问者也是如此(v) 相等约束。使两个约束语法相等的约束。(vi) 潜在的环境。形式x.e,绑定所有自由出现的在e中自由出现的x。我们使用符号x1。···,xn.e1. ···xn.e.(vii) 多态环境。这就促进了聚的论证中的粘合剂是多态的。(viii) 从属形式。标签标注的环境。诉Rahli等人/理论计算机科学电子笔记312(2015)1972033.1.4约束/环境的原子形式和语义设atoms(CL)是属于VarLabel的句法形式集,[医] CL. 此外,我们定义了如下所示的形式。变量(CL)=原子(CL)变量实验(CL)=原子(CL)变量标签注意,dom(atoms)=dom(labs)=dom(vars)=IntLabSynt,ran(atoms)=变量标签,ran(labs)=标签,ran(vars)=变量检查程序的不匹配部分需要替换、统一、重命名和访问隐藏的隐藏信息。本节将对这些概念进行定义。我们定义了重命名Ren和替换Sub的集合。 请注意,任俊燮。Ren∈ Ren ={ITyVar → ITyVar |ren是单射的<$dj(dom(ren),ran(ren))}sub∈Sub ={f1<$f2|f1∈Uni filer{f2∈TyConName→ TyConName}我们还定义了我们的单位集为有向无环图U ∈单位集={V,E}其中,V=ITyVar、ITyVar、ITyCon和E=P(V×V)指定方向边。注意,对于每个Vx∈V,边VxVxJ 最多发生一次,所以我们把U看作一个函数。当使用应用程序U(Vx)时,顶点VxJ将是返回其中存在从Vx到VxJ的路径(如果不存在,则Vx=VxJ),并且VxJVxJJ不存在,例如, 其中,U={{V1,V2,V3,V4,V5,V6},{V1V3,V3<$→V2,V4<$→V5,V2<$→V6}},U(V1)=V6.在应用过程中,如果U(v)=CLx且vars(CL)/={},则对于每个VJ∈vars(CL),如果U(VJ)/=VJ则用U(VJ)代替环境包含有关外部标识符的信息。我们还需要通过unifiers获得的内部类型变量的重命名用于实例化类型方案。Unifier集合由我们的约束求解器生成的unifier组成(见3.3节)。图3中定义了替换,其中给定一个约束项和一个替换,产生一个结果约束项。图 3约束条件上的替换语义(从约束条件到约束条件)约束条件)a[sub]=,x,如果sub(a)= x(n),ct)[sub]=10v。ct [sub] s.t. dj(v,atoms(sub))ctl[ sub]a,否则(图)e)[su b] =,n.[b] n.[b ] n.[b ]n.[c] n.[d] dj({a},atoms(sub))(ct1[sub]=ct2[sub])p↓oly(e)[sub] =p↓oly(e[sub])(τ μ)[sub]=(τ1<$τ2)[sub]==τ[sub]μ[sub](id=v)[sub]=(<$id=v[sub]),如果v[sub]∈Varτ1[sub]τ2[sub]<$未确定,否则ct[ sub]l( id=σ)[ sub]=( id=σ[ sub])(ct1=ct2)[sub]=(e1;e2)[sub]=e1[ sub]; e2[ sub]x[ sub]=x,否则204诉Rahli等人/理论计算机科学电子笔记312(2015)197⎪⎪⎩⎪⎨↓⎧⎩⎪3.1.5阴影、阴影和实例找到程序中的错误源就是访问并了解程序的每一位,以便识别任何不匹配。错误查找是难以捉摸的,因为在一个环境中,可能是某些部分被阴影覆盖,因此无法访问。考虑环境bind1;ev;bind2。在ev∈/dom(U)的情况下,我们认为ev影子绑定1是因为ev可能主要绑定到重新绑定绑定1的环境。我们通过以下方式定义阴影:• shadowsAll(U,e)阴影⎪⎧(e=ev∧(shadowsAl(⟨U,U(ev)⟩)∨ev/∈dom(U)(e=(e1;e2(e=(e=• shadowsAll(e)阴影shadowsAll(阴影,e阴影)请注意,dom(shadowsAll)=tuple(U×e)和ran(shadowsAll)要么为true,要么为false。我们现在介绍如何在下面的环境中访问标识符的语义,在约束求解过程中我们可以访问统一集U(id=σ)(id)=σ(e l)(id) = 10v. ct l,如果(e)(id)=bv. CT(e)(id),如果(e)(id)被定义22(ev)(id)=(e)(id),如果U(ev)=e未定义,否则(e;e)(id)如果(e2)(id)是unfined,(e)(id)=e(id)1 2andshadowsAll(U,e2)(e1)(id), 否则(e1)(id)=(e1;e2)(id)由于存在的环境代表不完全信息,它对识别者的应用是不确定的。最后,我们在这里定义了两个实例关系,它们的使用可以在约束求解中看到实例e实例好吧 c t,sub−→ct[su b]ifdom(su b)=vσ−→ctif<$su b. σ,sub−→e,ct3.2约束生成在本节中,我们将介绍约束生成器,它在用户程序的各个部分之间生成约束,这些部分以某种方式相互关联。我们的约束生成器如图4所示。请注意,在求解过程中还有其他类型的约束。设cstgenJ(PL,v)是一个有两个参数的函数,第一个参数是用户程序PL的标号部分,第二个参数是在PL中出现的自由变量集。每个、诉Rahli等人/理论计算机科学电子笔记312(2015)197205(Ⅲ)(Ⅲ)L1′2y=α1);ev;2;(α=α1233;(α2=α3)]4525;(α4=α5);ev21L82y=α1);ev;[345L1022L2L↓L2††L3聚乙烯(L9L12113l11L10的约束生成规则被写为PL=e(其表示cstgenJ(PL,{v})=e)或PL,v=e(其表示cstgenJ(PL,{v})=e)。 令cstgen(PL)=cstgenJ(PL,{})通过查看规则(G17)、(G14)和(G16)可以看出,数据类型声明只有一个构造函数。我们以这种方式定义核心是为了降低核心的复杂性。在规则(G13)中,我们定义数据类型名称只有一个类型变量参数。结构声明在规则(G20)中处理。为了降低复杂度,我们不处理核心中的签名,但这个理论可以在[11]中看到为了允许我们正确地划分环境,我们用标签来注释环境变量,比如规则(G4)。我们必须用一个标签来注释这样的环境变量,否则我们将无法将其切片,并且该环境变量将隐藏任何后续环境。为了为我们的运行示例生成约束,我们必须将规则(G4)应用于标记为fn-表达式的程序,并将规则(G6)应用于处理匿名函数的模式。这两个规则用于生成以下内容:[2019 - 04 - 25] (ev=↓ <$exp,α)→α)]这里的exp表示函数体,我们可以看到它是一个let语句。为此,我们使用规则(G2)来产生:[2014 - 10 - 15] <$dec);<$exp,α)其中dec表示声明,exp表示let语句的表达式。我们首先处理声明,应用规则(G17)为val rec语句创建约束,并应用规则(G6)处理函数(f)的名称,以给出:∃⟨α ,α ,ev ⟩.(evL8=poly(<$exp,α)约束继续以这种方式生成,直到我们达到该程序的最终生成约束,如下所示L[2019 - 04 - 25] (ev =↓α。α,α,ev - 是的(ev=L↓ f = α4;[α6,α7,ev 3]。(ev 3= ↓ x = α6); ev 3;α8,α9α。<$x=α8;<$y=α9;(α8=α9→α7);α5=6α7];(α4= α5); ev 2; α vα,α v。 f= α;y=α;(α=αα2);(α2=α3)];(α=α12α→l7l7′14小时L5′′16年′′→→α)]接下来,我们表明,约束生成的大小是线性的,我们的约束生成算法终止。引理3.1(约束生成的大小)约束生成在程序大小上是线性的2f=α4;L3L7L7206诉Rahli等人/理论计算机科学电子笔记312(2015)197)LL))L′(Ⅲ)L¢标记数据类型构造函数(ldcon)L;(α=α标记类型构造器(ltc)strid= ev); ev结构声明(strdec)结构表达式(strexp)L¢L¢¢LLL伊尔勒L)(e)†=L证据通过检查规则。对于一个多态的(let绑定的)函数(规则(G2),(G6)和(G17)),我们不急于复制函数体的约束。相反,我们生成多边形和复合环境,绑定器在每次使用函数复制其类型之前强制解决主体的约束Q图4约束生成器(ExtLabSynt →Env)表达式(exp)(G1)vidl,α=vidlα(G2)实验结束时,α)=[α2. <$dec);<$exp,α2);(α=α2)]L(G3)n.经验|l,α)= α1,α2 <$exp,α1);<$atexp,α2);(α1=α2<$α)(G4)fnpatlex p,α)=[α1,α2,ev. (ev=<$pat,α1));evl;<$exp,α2)1α2)](G5)dcon l,α=dcon=α†模式(pat)(G6)vvarl,α=l(G7)dconl,α=l<$p)↓vvar=α<$p)<$dcon=α;(α=α(八国集团)[ldcon atpat |l,α)= α1,α2 <$ldcon,α1);<$atpat,α2)12α)(G9)tcl,δ=tc=δ†类型(ty)(G10)tvl,α=tv=α†LL′(G11)[ty ltc|,α)= δα,δα。<$ty,α);<$ltc,δ)LL;(α=αδ)(G12)ty → ty,α)= α1,α2,α1。<$ty,α1);<$ty,α2)数据类型名称(dn)(1)¢1 21 2;(α=α(G13)¢[电视tc|l,α′)= εα,γε。(α′=αγ);(↓tc=γ);(↓tv=α)构造函数绑定(cb)(G14)dconl,α=l(G16)lty的dcon,α = α 1α′,α1。(1)1α);(↓(c)↓dcon=α<$);(α=αdcon=α)声明(12月)(G17)=α1,α2,ev α。(ev=poly(tpat,α1); texp,α2)12LLLLL(1)valrecpat=exp);(α=α);ev(G18)=α1,α2,ev12 dn,α1);poly(cb,α2);ev数据类型dn=cb(G19)<$openlstrid)= ev. (†LL诉Rahli等人/理论计算机科学电子笔记312(2015)197207′. (ev=((αL=a);(G20)结构strid=strexp) =ev,ev ′. [<$strexp, ev)];(ev′=(↓strid=ev));ev′l(G21)strid1, ev=strid=ev208诉Rahli等人/理论计算机科学电子笔记312(2015)197†诉Rahli等人/理论计算机科学电子笔记312(2015)197209(G22)struct1strdec1···strdecn end,ev)=struct1strdec n end,ev)= struct 1 strdec210诉Rahli等人/理论计算机科学电子笔记312(2015)197nend,ev)= struct 1 strdec n end,ev)=struct 1strdec n end,ev)= struct 1 strdec n诉Rahli等人/理论计算机科学电子笔记312(2015)197211end,ev升212诉Rahli等人/理论计算机科学电子笔记312(2015)197<$strdec1); ···;<$strdecn)诉Rahli等人/理论计算机科学电子笔记312(2015)197213等。(1)(2)(214诉Rahli等人/理论计算机科学电子笔记312(2015)197引理3.2(约束生成算法的终止)图4所示的应变发生器终止。诉Rahli等人/理论计算机科学电子笔记312(2015)197215证据 让我们将原子约束生成规则定义为约束生成216诉Rahli等人/理论计算机科学电子笔记312(2015)197不创建递归调用的规则,例如,原子约束生成
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 5
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- OptiX传输试题与SDH基础知识
- C++Builder函数详解与应用
- Linux shell (bash) 文件与字符串比较运算符详解
- Adam Gawne-Cain解读英文版WKT格式与常见投影标准
- dos命令详解:基础操作与网络测试必备
- Windows 蓝屏代码解析与处理指南
- PSoC CY8C24533在电动自行车控制器设计中的应用
- PHP整合FCKeditor网页编辑器教程
- Java Swing计算器源码示例:初学者入门教程
- Eclipse平台上的可视化开发:使用VEP与SWT
- 软件工程CASE工具实践指南
- AIX LVM详解:网络存储架构与管理
- 递归算法解析:文件系统、XML与树图
- 使用Struts2与MySQL构建Web登录验证教程
- PHP5 CLI模式:用PHP编写Shell脚本教程
- MyBatis与Spring完美整合:1.0.0-RC3详解
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功