CN117355818A - 防止最小运行时上的垃圾对象积累 - Google Patents

防止最小运行时上的垃圾对象积累 Download PDF

Info

Publication number
CN117355818A
CN117355818A CN202180094311.7A CN202180094311A CN117355818A CN 117355818 A CN117355818 A CN 117355818A CN 202180094311 A CN202180094311 A CN 202180094311A CN 117355818 A CN117355818 A CN 117355818A
Authority
CN
China
Prior art keywords
data type
data
source code
definition
programming language
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN202180094311.7A
Other languages
English (en)
Inventor
M·V·塞缪尔
J·纳格拉
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Tamper Systems Inc
Original Assignee
Tamper Systems Inc
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Tamper Systems Inc filed Critical Tamper Systems Inc
Publication of CN117355818A publication Critical patent/CN117355818A/zh
Pending legal-status Critical Current

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F8/00Arrangements for software engineering
    • G06F8/40Transformation of program code
    • G06F8/41Compilation
    • G06F8/43Checking; Contextual analysis
    • G06F8/436Semantic checking
    • G06F8/437Type checking
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F16/00Information retrieval; Database structures therefor; File system structures therefor
    • G06F16/90Details of database functions independent of the retrieved data types
    • G06F16/901Indexing; Data structures therefor; Storage structures
    • G06F16/9024Graphs; Linked lists

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • General Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Databases & Information Systems (AREA)
  • Computational Linguistics (AREA)
  • Data Mining & Analysis (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

计算机实施技术被用于防止最小运行时上的垃圾对象积累。所述技术包含检查以源编程语言写入的源代码是否无需程序员显式编程在很少或根本不支持隐式解除分配的运行时内何时可运行解除分配。在同一时间,所述技术确保以及时方式将最小运行时中的对象解除分配。一方面,所述技术囊括在检测到所述源代码中的数据类型定义具有潜在引用循环之后即刻向源代码程序员生成编译时警示或暂停对所述源代码的编译。利用所述技术,所述程序员在产生与最小运行时互操作的程序片段的同时获得隐式解除分配体验,所述最小运行时不提供或仅提供对隐式解除分配的最小支持(例如,仅提供引用计数)。

Description

防止最小运行时上的垃圾对象积累
技术领域
本公开涉及计算机编程语言编译器。更具体来说,本公开涉及用于防止最小运行时上的垃圾对象积累的计算机实施技术。
背景技术
计算机是用于执行各种各样任务的非常强大的工具。计算机程序是用于使用计算机系统来实现定制处理任务的通用机制。典型程序是编译成可执行形式的一组经编程指令(源代码)。然后,可执行形式由计算机系统执行以实现任务。例如,一组C编程语言指令可被编译成一组x86处理器可执行指令。然后,所述一组处理器可执行指令可由x86兼容处理器执行以实现处理任务。
在如由人类计算机程序员编程的一组经编程指令与可执行形式之间,编译器通常用作翻译器。本质上,编译器保护程序员免于了解或甚至无需担心底层可执行形式细节。通常,由程序员编写的所有经编程指令都由编译器翻译。例如,编译器可执行数据类型检查、符号表构造、寄存器分配及指令调度,所有这些都无需程序员了解底层编译器实施方式。以这种方式,编译器向程序员提供使用高级编程语言在更高级别上推理及表达处理任务的工具,这减轻了程序员担心低级执行细节的认知负担。编译器的一般构造及操作在本领域中是众所周知的。参见例如Aho,A.、Sethi,R.及Ullman,J.的“编译器:原理、技术及工具(Compilers:Principles,Techniques,and Tools)”,第二版,2007年。
一些编译器的一个目的是交叉编译。交叉编译器可被定义为从一个输入产生两个或更多个输出的编译器。例如,交叉编译器可接受由人类及计算机可读两者的源编程语言写入的源代码作为输入,并产生源代码的一种或多种可执行形式作为输出。例如,考虑了C编程语言的交叉编译器。此种交叉编译器可从C源代码产生x86可执行文件(例如,用于在配置有MICROSOFT WINDOWS操作系统的计算机上执行)、ARM可执行文件(例如,用于在配置有ANDROID操作系统的移动计算装置上执行)以及WASM可执行文件(例如,用于在由web浏览器应用支持的虚拟堆栈机器上执行)。
还存在源到源编译器。源到源编译器可被定义为这样的编译器:接受以人类及计算机可读两者的源编程语言写入的源代码作为输入,并且输出用于人类及计算机可读两者的一个或多个编程语言目标的源代码。例如,HAXE编译器可将以HAXE编程语言写入的源代码翻译成一些结构上类似的编程语言目标。关于HAXE的更多信息可在互联网上在haxe.org互联网域中找到。
如今,许多广泛使用的编程语言都支持运行时隐式对象解除分配。解除分配可被定义为释放被非必要对象占用的计算机存储器空间以便可再次使用所述空间的运行时操作。如果空间最终被释放,诸如例如在对象变得非必要之后不久或者当执行程序确定所述空间需要用于其它目的时,那么在运行时解除分配是及时的。未以及时方式解除分配的对象有时被称为存储器“泄漏”。
一些编程语言需要显式经编程解除分配,而另一些则支持隐式运行时解除分配。利用显式解除分配,计算机程序由程序员明确地编程,以使用诸如“new”、“malloc”、“free”、“delete”等等编程语言操作来为运行时对象分配及解除分配存储器空间。利用隐式运行时解除分配,程序员不再需要负责明确地编程程序来为运行时对象分配及解除分配存储器空间。而是,编程语言运行时负责将运行时对象及时解除分配。
为了支持运行时隐式对象解除分配,编程语言运行时可提供运行时存储器管理服务,包含周期性地识别存储器中可被安全解除分配的对象的垃圾收集器或者识别存储器中相互引用但不被执行程序的其它部分引用的对象群组的循环收集器。然后可释放由对象占用的存储器空间以供其它用途。
还存在智能引用。智能引用将存储器地址位与控制如何将存储器区域解除分配的其它位组合。一个种类的智能引用的示例是保持对需要所引用对象的程序元素的数目进行计数的引用计数引用。当计数达到零时,该对象可被安全解除分配。智能引用可与不针对隐式解除分配提供运行时支持的一些编程语言搭配使用。现代C++编程语言是一个示例。
如今,大多数计算机程序员习惯于以支持运行时隐式解除分配的编程语言来进行编程。不幸的是,仍存在不支持运行时隐式解除分配的许多广泛使用的编程语言。此类编程语言的示例包含C、C++、OBJECTIVE-C及RUST。经设计以支持所有广泛使用的编程语言的交叉编译器或源到源编译器不能假设所有目标都提供运行时隐式解除分配
本文中所公开的技术解决了这个问题及其它问题。
本节中所描述的方法是可追求的方法,但未必是先前所设想或所追求的方法。因此,除非另有指示,否则不应假设本节中所描述的任何方法仅仅因为包含在本节中就有资格作为现有技术。
附图说明
在附图的各图中,所述技术是通过示例方式而非通过限制方式来图解说明的,并且其中相似参考标记指代类似元件,且在各图中:
图1描绘循环数据结构的第一示例。
图2图解说明使用外观方法来提供实际上非循环数据结构的表观循环视图的第一示例。
图3描绘循环数据结构的第二示例。
图4图解说明使用外观方法来提供实际上非循环数据结构的表观循环视图的第二示例。
图5A、图5B、图5C、图5D、图5E、图5F一起描绘使用外观方法来提供实际非循环数据结构的表观循环视图的示例。
图6A、图6B、图6C各自描绘数据类型定义图的示例。
图7A、图7B、图7C、图7D、图7E、图7F、图7G、图7H是数据类型检查过程的流程图。
图8是可在技术的实施方式中使用的示例性基本计算装置的框图。
图9是可用于控制图8的基本计算装置的操作的示例性基本软件系统的框图。
发明内容
以下具体实施方式的总体概述部分提供用于防止最小运行时上的垃圾对象积累的技术的有用概述。
在一些实施例中,编译器或数据类型检查工具检查编程语言源代码中的数据类型定义并且引起程序员注意可允许运行时引用循环的任何定义。在一些实施例中,所述编译器或数据类型检查工具考虑了计算机程序如何使用类型定义。
在一些实施例中,所述编译器或数据类型检查工具考虑了编程语言源代码中的数据类型定义的哪些性质定义是只读的。在一些实施例中,所述编译器或数据类型检查工具使用所述编程语言源代码中的显式提示来确定性质定义是否是只读的,所述性质定义包含诸如“const”、“final”或“read-only”等关键字或者注解,或者不存在诸如“mutable”或“writeable”等具有相反含义的显式提示。在一些实施例中,所述编译器或数据类型检查工具检验性质定义以推断只读性。例如,当在性质的初始值被指派之后可设定性质的所述编程语言源代码中任一者都不这样做时,可推断性质定义的只读性。在一些实施例中,所述编译器或数据类型检查工具将额外指令插入到编程语言源代码或可执行程序中以检测或强制执行所需只读性。例如,在性质被初始化之后,所述额外指令可能会致使对所述性质的值指派失败。
在一些实施例中,所述编译器或数据类型检查工具考虑了在对含有的对象的任何引用之前将所述编程语言源代码中的哪些性质定义早期初始化。早期概念是用来防止对象在性质初始化期间创建对自身的引用循环。可基于对将性质初始化的编程语言源的检验来推断早期初始化。早期初始化也可基于显式提示。所述显式提示可致使对可能执行初始化的所述编程语言源代码的其它检查,诸如例如检查数据类型的构造符定义以检查使用“this”引用作为值与性质指派之间的时间关系。所述编译器或数据类型检查工具可将额外指令插入到编程语言源代码或可执行程序中以检测或强制执行所需早期性。例如,在对含有性质的所述对象的“this”引用被用作值之后,所述额外指令可能导致将所述性质初始化的尝试失败。
在一些实施例中,所述编译器或数据类型检查工具考虑了数据类型定义是否是封闭的(例如,其所有子类型是否对所述编译器或数据类型检查工具是已知的)。封闭性可基于所述编程语言源代码中的显式提示,诸如通过如同“final”、“closed”、“sealed”等关键字或注解的存在,或者如同“open”等具有相反意义的提示的不存在。封闭性可基于上下文来推断。例如,如果对数据类型定义的访问被信息隐藏机制限制于所述编程语言源代码的一些模块,并且在那些模块内的所述编程语言源代码中不存在子类型的定义,那么可推断所述数据类型定义的封闭性。封闭性还可用于允许用基于情形的推理来代替关于通用超数据类型的推理。
在一些实施例中,所述编译器或数据类型检查工具考虑了数据类型定义是否是具体的(例如,是否可存在那种数据类型的并非所述数据类型的子数据类型的值的值)。具体数据类型可与抽象数据类型形成对比,所述抽象数据类型不足以描述值但可从中派生具体子数据类型。具体性可基于显式提示,诸如例如通过如同“concrete”等关键字或注解的存在,或者如同“abstract”等关键字或注解的不存在。具体性可基于上下文诸如例如通过所述编程语言源代码中的所述数据类型的用户来构造对象或者通过不存在会防止构造全功能对象的任何缺失件来推断。所述编译器或数据类型检查工具可推理具体类型足以进行引用循环检测,因为在运行时创建的所有值必须是至少一种具体数据类型。
在一些实施例中,所述编译器或数据类型检查工具通过构建潜在类型含有关系的图形来检查潜在引用循环。所述图形中的一些节点可对应于所述编程语言源代码中所定义的数据类型。所述图形中的一些节点可对应于关于泛型类型参数的最坏情形假设。所述最坏情形的假设可能会考虑泛型类型参数的界限或者数据类型定义的界限。数据类型定义的一种类型的界限在本文中被称为“不可引用”界限。所述图形中的一些边可对应于所述编程语言源代码中所定义的一种数据类型可引用所述编程语言源代码中所定义的另一数据类型的方式。图形元素(例如,节点及边)可与从性质及数据类型定义的所述早期性、只读性或封闭性派生的元数据相关联。在一些实施例中,所述图形中具有特定种类的边的循环对应于所述编程语言源代码中的一组一个或多个数据类型定义所允许的可能引用循环。
由所述编译器或数据类型检查工具生成的警示可包含可能引用循环的人类可读描述。例如,描述可能会这样说:“类型Thing的值可经由其性质otherThing引用自身。‘aThing.otherThing=aThing;’将创建引用循环。”此种描述可从与潜在类型含有关系的图形中的节点或边相关联的元数据派生。所述描述可包含关于如何纠正问题的建议(例如,如何避免所述潜在引用循环)。在一些实施例中,诸如集成式开发环境的外部工具使用所述警示或所述警示的所修改形式(例如,所述警示的更机器可读形式)基于程序员用户所选择的建议来自动改变所述编程语言源代码。
在一些实施例中,所述编译器或数据类型检查工具忽略已被人类审阅者认为安全的潜在引用循环。识别已被认为安全的引用循环可基于提示、注解或与所述编程语言源代码中的数据类型定义相关联的其它元数据。识别已被认为安全的引用循环可替代或也基于确定仅在所述编译器或数据类型检查工具免除数据类型检查的所述编程语言源代码的“不安全”片段内部指派所涉及性质,以便人类审计员可批准需要允许引用循环的数据类型定义。
在一些实施例中,分布式对象系统保留同一计算机上的其它计算机或过程所需的对象的引用计数,并且依赖于非循环性检查以避免必须检测一些类型的对象之间的引用循环。在此上下文中,对象可引用其它过程中存在的对象,并且当所述分布式系统中的过程不再需要对象时,其可将消息发送给所述系统中被认为拥有所述对象的所述过程。所述系统中的多个过程可针对同一对象维护单独引用计数,以处置其中所述过程中的一者死亡或失败的情形,或者处置其中所述过程中的一者行为不当的情形,诸如例如,通过声称其不再需要两个引用,而其开始时只有不到两个引用,这可能是为了使那个对象对其它过程不可用。
具体实施方式
在以下描述中,出于解释目的,陈述了众多具体细节以提供对所述技术的透彻理解。然而,显而易见的是,所述技术可在没有这些具体细节的情况下实践。在其它实例中,众所周知的结构及装置是以框图形式展示的以便避免不必要地模糊所述技术。
词汇表
提供以下定义是为了说明性目的而不是限制性目的,以帮助理解本技术的公开内容:
客户端:“客户端”可被定义为将任务委托给库的计算机系统的一部分。
编译器:“编译器”消耗适合于人类及机器消耗两者的输入并产生一个或多个输出。每一输出都是编译器对输入的翻译。例如,输入可以是以源编程语言写入的源代码。输出可以是输入源代码的可执行形式。输出还可呈与源编程语言不同的目标编程语言的输入源代码的源代码形式。
交叉编译器:“交叉编译器”是从一个输入产生两个或更多个输出的编译器。
解除分配:术语“解除分配”是指在正在执行的计算机程序的上下文中释放由非必要对象占用的存储器空间以供再次使用的运行时操作。
垃圾对象:“垃圾对象”是可安全地解除分配但尚未解除分配的对象。
图形:“图形”是用于建模实体之间的成对关系的数学结构。在此上下文中,图形通常由通过边(也称为链接或线)连接的顶点(也称为节点或点)组成。计算机程序可以各种不同方式来表示图形,包含经由引用边对象的节点对象,所述边对象引用节点对象。其它可能方式包含经由邻近矩阵、关联矩阵或邻近列表。
库:“库”可被定义为一个或多个算法以可自动化形式的表达式。可自动化形式的示例可以是编程语言代码或其经编译版本(例如,作为字节码、二进制可执行代码等)。通常,当作为一个或多个过程执行时,库并不“拥有”作为其一部分执行的过程。相反,库与更大系统一起执行,或者作为更大系统的一部分执行,所述更大系统将特定种类的算法任务委托给所述库。例如,计算机网络上的微服务可被视为库。微服务经常针对其它网络节点存在以删除特定算法任务。
对象:“对象”可被定义为可响应于计算机程序内的消息的运行时实体。所述实体通常占用计算机存储器的区域。对象可响应于消息并根据数据类型定义来组织所占用存储器区域中的位。对象的一个示例是根据面向对象的编程语言的类定义的运行时实例。
引用:“引用”是使得计算机程序能够访问存储在计算机存储器中的位置处的对象的运行时值。使用引用来获取存储在所述位置处的对象有时被称为解除引用。“指针”是引用的一个示例。
运行时:用于编程语言的“运行时”囊括支持执行以那种语言写入的计算机程序的计算机制。例如,用于编程语言的运行时可囊括理解那种语言的计算机程序被编译成的字节码指令的虚拟机。JAVA虚拟机(JVM)只是此种运行时的一个示例。运行时还可提供隐式解除分配服务,诸如垃圾收集或循环收集。然而,并非所有运行时都提供隐式解除分配服务。另外,本文中所使用的术语“运行时”是指计算机程序被执行的时间。
目标:“目标”可被定义为客户端用来连接到编译器输出的机制。编程语言可以是目标;程序员写入代码来连接到加载到同一存储器空间中的库。虚拟机(VM)可以是目标;程序员可写入代码,代码被编译成虚拟机运行的字节码种类并依赖于VM经由接口链接使用。另一程序可以是客户端。因此,程序间机制是目标;代码可使用过程间通信(IPC)、远程程序叫用(RPC)或RESTful网络协议将消息发送给在客户端程序的过程之外运行的某个程序(诸如,例如网络服务或微服务),并辨识传入消息何时含有响应。
总体概述
计算机程序中的未经解析引用循环可能会导致运行时垃圾对象的堆积。此种堆积可能会致使灾难性程序失败。为了进行说明,请考虑PYTHON编程语言。更老版本的PYTHON运行时使用进行引用计数来保持对所分配存储器的跟踪。特定来说,PYTHON中的运行时对象具有指示有多少对象正在引用其的引用计数。当引用计数达到零时,将对象从存储器释放。进行引用计数对于大多数PYTHON程序都可很好地工作,以防止垃圾对象的堆积。然而,当存在“引用”循环时,进行引用计数可能会失败。当对象相互引用时,引用循环就会发生。
考虑了以下简单PYTHON程序,所述程序创建列表对象,将对所述列表的引用存储在列表本身的元素中,且然后删除所述列表对象。
00:l=[]
01:l.append(l)
02:del l
第00行处的语句创建列表并将所述列表的引用计数增加到1。第01行处的语句将对列表的引用添加到列表本身,从而产生引用循环并将所述列表的引用计数增加到2。第02行处的语句通过变量‘l’删除了对列表的引用,并将所述列表的引用计数从2减少到1。由于引用循环,列表中的引用计数为1,因为第01行处的语句创建了内部保存的自引用。结果,仅通过进行引用计数不会将列表隐式解除分配。这是非所期望的,因为所述列表在第02行处的语句之后无法使用,并且应被解除分配。
虽然在计算机程序中故意创建引用循环通常不被认为是良好编程实践,但有时难以避免创建引用循环,并且其它时间程序员并不知道将创建引用循环。对于长时间运行的程序(诸如服务器程序),如果服务器程序耗尽存储器,这可能会出现问题,并且甚至可能是灾难性的,因为仅引用计数无法将不可用对象解除分配。
为了解决引用计数的这个缺点,一些版本的PYTHON运行时使用在运行时查找正在执行的PYTHON程序中的引用循环的垃圾收集器。进行引用计数仍用于将其它对象解除分配。尽管如此,对象“终结器”仍可能存在问题。“终结器”是将对象解除分配时需要发生的一组一个或多个操作。终结器经常用于释放如同操作系统文件描述符等系统资源,其数目可能受到限制。PYTHON中终结器的示例是对象的“__del__”方法(例如,提供特殊PYTHON“__del__”方法的实施方式的类的实例)。
利用进行引用计数,当对象的引用计数变为零时,将在将对象解除分配之前叫用终结器。然而,利用垃圾收集,程序员在运行时推理终结器的行为变得更困难,尤其是当存在引用循环时。例如,如果引用循环中的两个对象都具有终结器,那么应该首先叫用哪个终结器?在叫用终结器中的一者之后,无法释放对象,因为另一终结器可能仍需要访问所述对象。面对这种情况,在对象创建引用循环的情况下,一些版本的PYTHON运行时不会利用终结器将对象解除分配。而是,所述对象被添加到不可收集垃圾对象的全局列表。PYTHON程序可经编程以访问全局列表并以对手边特定应用有意义的方式显式释放引用循环。当然,这假设程序员知道可首先创建引用循环。即使这样,程序员也必须将全局列表中的对象小心地解除分配。
从前述PYTHON示例清楚的,向运行时添加对隐式解除分配的支持可能会带来复杂性。PYTHON运行时在C或C++运行时内运行的事实有助于如PYTHON情形一样添加垃圾收集。然而,添加对可能嵌入其它运行时的C或C++运行时的支持并不简单。例如,各个运行时需要将彼此的引用辨识为引用,并一致同意哪个运行时负责执行解除分配。
一般来说,从程序员的角度来看,至少存在两种引用循环:(1)有意引用循环;及(2)非有意引用循环。诸如树等递归数据类型可能是非有意引用循环的源。例如,列表中的列表可避免引用循环,如果其使用被仔细编程的话。然而,如上文的PYTHON示例所证明,在许多编程语言中,可能会无意创建无法在运行时通过简单引用计数来理清的引用循环。
本文中所公开的技术解决了这些问题及其它问题。
计算机实施技术被提供用于防止最小运行时上的垃圾对象积累。所述技术包含检查以源编程语言写入的源代码是否无需程序员显式编程在很少或根本不支持隐式解除分配的运行时内何时可运行解除分配。在同一时间,所述技术确保以及时方式将最小运行时中的对象解除分配。
所述技术囊括向源编程语言中的源代码的程序员生成编译时警示(例如,错误或警告消息),或者在检测到源代码中具有引用循环的可能性的数据类型定义时暂停源代码的编译。所述技术足够灵活来允许程序员以源代码定义表观上循环但实际上非循环的数据类型。所述技术也足够灵活来允许程序员以源代码定义递归但非自引用的数据类型。利用所述技术,所述程序员在产生与最小运行时互操作的程序片段的同时获得隐式解除分配体验,所述最小运行时不提供或仅提供对隐式解除分配的最小支持(例如,仅提供引用计数)。
依据结合附图的以下详细描述,本技术的这些及其它方面将变得显而易见,附图通过示例方式图解说明所述技术的原理。
不具有实际循环的表观循环
如所指示,程序员可以源编程语言对源代码进行编程,目的是允许引用循环。例如,程序员可对源代码进行编程来定义递归数据类型。递归数据类型是引用其自身数据类型定义的数据类型。
例如,考虑了可能的源编程语言中的以下数据类型定义:
00:closed type List<E>;
01:closed concrete type Cons<F>extends List<F>{
02:initial:F;
03:rest:List<F>;
04:}
05:closed concrete type Empty<G>extends List<G>{}
根据上述数据类型定义,初始性质被定义为泛型数据类型,并且其余性质被定义为List<F>类型,其是Cons<F>类型的父类型。这样一来,Cons<F>对象的初始及其余性质中的任一者或两者可引用Cons<F>对象本身。因此,Cons<F>数据类型是递归数据类型。
在上述数据类型定义中,封闭式关键字规定编译器已知所述数据类型的所有子数据类型,这与可扩展数据类型相反,在可扩展数据类型中,可在事后规定所述数据类型的额外子数据类型。在一些实施方式中,封闭式数据类型是默认的,并且因此如果需要封闭式数据类型,那么无需指定封闭式关键字。
作为另一示例,考虑了可能的源编程语言中的二进制树的以下数据类型定义:
00:closed type Tree<B>;
01:closed concrete type BinaryTree<F>extends Tree<F>{
02:element:F;
03:left:Tree<F>;
04:right:Tree<F>;
05:}
06:closed concrete type Empty<G>extends Tree<G>{}
上述数据类型定义将泛型数据类型BinaryTree<F>定义为一组值。根据上述类型定义,BinaryTree<F>对象的left及right性质中的任一者或两者可含有BinaryTree<F>类型的值。因此,BinaryTree<F>数据类型也是递归数据类型。
如所提及,递归数据类型的实例可发展成运行时引用循环。图1描绘运行时对象的示例性循环集合。例如,对象的集合可表示树或图形数据结构。椭圆表示计算机存储器中的运行时对象,并且有向边表示从一个对象到另一对象的引用。例如,对象1通过引用d来引用对象2。示例性集合中存在众多引用循环,如不同方向上的有向边所描绘。例如,如果数据对象的集合表示树数据结构,那么从对象6及到对象7的引用u可表示对象7是对象6的树中的第一子节点,在那种情形中,引用v可表示对象7是对象6的树中的最后子节点,并且引用t可表示对象7是对象6的树中的父节点,等等。
外观方法
所述技术囊括外观方法。根据外观方法,不是通过相互引用的节点及边的分类来表示运行时对象之间的关系,而是可使用外观方法来表示运行时对象之间的关系。利用外观方法,对象的集合对于执行程序来说可能看起来是循环的(即,表观上是循环的),但其运行时实施方式实际上是非循环的。因为其运行时实施方式实际上是非循环的,所以无需隐式运行时解除分配支持,诸如自动垃圾收集器或自动循环收集器。而是,可使用进行简单引用计数机制来将对象及时解除分配。
将源编程语言中的源代码翻译为不支持运行时隐式对象解除分配的目标编程语言中的源代码的源到源编译器可生成目标源代码以使用外观方法。通过这样做,目标编程语言运行时可将对象及时解除分配,而无需支持隐式运行时解除分配。与外观方法结合,源编程语言可向程序员提供隐式解除分配编程体验,其中程序员无需关心以源编程语言对源代码进行编程来明确地分配及解除分配对象。即使源到源编译器的目标语言中的一种或多种不支持隐式运行时解除分配,也提供这种体验。还允许程序员以源编程语言来定义递归数据类型。由于对象在运行时的表示表观上是循环的,但实际上并非循环的,因此引用循环不会在运行时被创建。
外观方法使用了更大分类。特定来说,更大分类包括:
·“数据”对象,其是所定义数据类型的实例,
·“关系”对象,其收集数据对象之间的关系,
·“图形”对象,其将数据对象与关系对象配对,及
·“外观”对象,其呈现类循环表观,并且是指数据对象及图形对象。
根据外观方法,运行时程序访问并修改以源编程语言来编程的数据对象的集合,以允许引用循环。例如,数据对象的集合可表示基于以源编程语言定义的递归数据类型的数据结构。例如,数据结构可以是列表、树或图形数据结构,其中数据结构的对象是递归数据类型的实例。
外观方法通过外观对象提供了一种运行时机制,数据对象的集合可通过所述运行时机制来维持非循环性。正是通过外观对象,表观循环数据对象的集合维持了其实际非循环性,尽管其表观对于程序来说是循环的。由于维持了非循环性,因此无需运行时垃圾收集或引用循环检测来将数据对象的集合及时解除分配。
在外观方法的分类中,给定外观对象最多对应于最多一个图形对象及最多一个数据对象。然而,多个外观对象可对应于同一数据对象。给定图形对象可对应于一个或多个关系对象,并且给定关系对象可对应于一个或多个数据对象。这样一来,给定图形对象可通过给定图形对象所对应的一个或多个关系对象来对应于一个或多个数据对象。
图2描绘外观方法到图1中所描绘的对象的示例性循环集合的示例性应用。如图2中可看到,对象的循环集合在运行时被表示为对象的非循环集合。在此示例中,仅存在数据对象1、4及6的外观对象,而没有数据对象2、3、5及7的外观对象。可能存在不同的一组外观对象,包含一组仅具有一个外观对象以及一组包含同一底层数据对象的多个外观对象。此外,取决于程序相对于数据对象的集合的访问及修改型式,可在运行程序的过程中在不同时间针对数据对象的集合创建不同的若干组外观对象。
在运行时,对集合中数据对象的引用是经由数据对象的外观对象进行的。例如,参考图2,如果程序使用外观对象6来请求在引用f的另一端处的数据对象1,那么外观对象1被提供给程序,而不是提供数据对象1或对数据对象1的引用。例如,外观对象1可由外观对象6的经计算性质抽象概念来提供。
为了在运行时确定哪个数据对象位于引用的另一端处,外观对象可使用图形对象。图形对象可囊括映射对象。映射对象将数据对象与关系对象配对。例如,图2的映射对象可将数据对象6及数据对象1映射到关系对象X。特定来说,当程序使用数据对象6的外观对象6来引用在引用f的另一端处的数据对象时,外观对象6又使用图形对象及映射对象来确定由图形对象引用的哪个关系对象经由引用f来收集数据对象6与数据对象1之间的关系。外观对象6然后可创建外观对象1。这样做时,外观对象1被创建或配置为引用外观对象6经由关系对象X获得的数据对象1。外观对象1也被创建或配置为引用图形对象。这展示于图2中。然后,外观对象6将外观对象1而不是数据对象1返回给叫用程序,以维持数据对象的集合的表观循环性及实际非循环性。
映射对象可以各种方式来构造。例如,映射对象可囊括二维数组,其中数组的每一元素对应于一对数据对象并指示对所述一对数据对象之间的所有关系进行分组的关系对象。例如,如果M是二维数组,那么M[x][y]引用对数据对象x与数据对象y之间的所有关系进行分组的关系对象。作为二维数组的替代,M[x][y]可引用对从数据对象x到数据对象y(或从数据对象y到数据对象x)的所有关系进行分组的关系对象。另一选择是,映射对象可囊括一维数组,其中每一数组元素对应于数据对象以及将从那个数据对象到其它数据对象的所有关系分组的关系对象。例如,M[x]可引用对从数据对象x到其它数据对象的所有关系进行分组的关系对象。
当数据对象被添加到运行时集合时,其可能会连接到图形对象。例如,图3描绘图1的数据对象的循环集合,但添加了数据对象8,所述数据对象8具有与数据对象4的引用w及x。引用w及x在图3的对象的循环集合中创建引用循环。图4描绘添加了数据对象8的对象的集合的表观循环但实际非循环表示。特定来说,图形对象的映射对象可被更新以将数据对象8及数据对象4映射到关系对象Y。关系对象Y收集数据对象8与数据对象4之间的w及x关系。
在外观方法下,数据对象可经由图形对象建立与另一数据对象的关系。这对如何将数据对象添加到现有数据结构有影响。例如,考虑了可能的源编程语言中的以下源代码:
00:let root=BinaryTree(“root”,Empty,Empty);
01:let left=BinaryTree(“left”,Empty,Empty);
02:root.left=left;
第00行创建“root”数据对象作为上文所论述的BinaryTree<F>递归数据类型的实例。图5A描绘根据外观方法在上述第00行处创建的“root”数据对象的非循环运行时表示。不是直接引用“root”数据对象,而是变量“root”是引用“root”数据对象及“root”图形对象的外观对象。就这一点来说,在执行中,第01行处的“left”对象实例尚未被创建。因此,“root”关系对象不对“root”数据对象与“left”对象之间的任何关系进行分组。
第01行创建“left”数据对象作为上文所论述的BinaryTree<F>递归数据类型的实例。图5B描绘根据外观方法在上述第01行处创建的“left”数据对象的非循环运行时表示。不是直接引用“left”数据对象,而是变量“left”是引用“left”数据对象及“left”图形对象的外观对象,所述“left”图形对象可以是与“root”数据对象的“root”外观对象所引用的“root”图形对象(如图5A中所描绘)不同的图形对象。就这一点来说,在执行中,“root”数据对象与“left”数据对象之间仍然没有关系。这样一来,引用“left”数据对象的“left”关系对象也不对“root”对象与“left”对象之间的任何关系进行分组。“left关系对象可以是与“root”关系对象不同的关系对象,所述“root”关系对象如图5A中所描绘引用“root”数据对象。
第02行设定“root”对象的left性质来引用“left”数据对象。在没有外观方法的情况下,“root”数据对象的left性质可能直接引用运行时“left”数据对象。然而,利用外观方法,当源编程语言中的源代码被编译为不支持隐式运行时解除分配的目标编程语言中的源代码时,防止此种直接引用。具体来说,目标语言中的源代码经编译以在运行时实施外观方法,使得当目标语言源代码被编译成可执行文件并被执行时,防止直接引用。
图5C描绘根据外观方法的在“root”数据对象的left性质被指派为引用“left”数据对象之后“root”及“left”数据对象的非循环运行时表示。root及left外观对象现在共享同一图形对象。具体来说,由“left”外观对象(图5B)引用的“left”图形对象已被导入由“root”外观对象(图5A)引用的“root”图形对象中。这样做时,“left”外观对象被更新以引用“root”图形对象并且不再引用“left”图形对象。由“root”图形对象引用的“root”关系对象被更新以引用“left”数据对象,并且left图形中的“left”关系对象与“left”数据对象断开连接。left图形的“left”图形对象现可被解除分配,因为其引用计数为零。一旦“left”图形对象被解除分配,“left”图形对象的“left”映射对象以及“left”关系对象就可被解除分配,因为在“left”图形对象被解除分配之后其引用计数应为零。“root”图形对象的“root”映射对象被更新以规定“root”数据对象与left“数据对象”具有关系,并且那种关系由“root”关系对象分组。
图5C的非循环表示在运行时表示“root”数据对象的left性质直接引用“left”数据对象的概念,如图5D中所图解说明。
除了上述源代码以外,现考虑可能的源编程语言中的以下源代码:
03:left.right=root;
04:let extra=root;
在没有外观方法的情况下,上述第03行处的额外源代码将在“root”数据对象与“left”数据对象之间创建运行时引用循环。然而,利用外观方法,可避免引用循环。这展示于图5E中,图5E描绘根据外观方法的在“left”数据对象的right性质被指派为通过外观对象引用“root”数据对象(如上述第03行中所示)之后“root”及“left”数据对象的非循环运行时表示。“root”及“left”数据对象仍共享“root”关系对象,“root”关系对象将(1)通过“root”数据对象的left性质的“root”数据对象与“left”数据对象之间的关系以及(2)通过“left”数据对象的right性质来创建的“root”数据对象与“left”数据对象之间的关系两者进行分组。被命名为“extra”的变量是引用“root”图形对象及“root”数据对象的外观对象。
除了上述源代码以外,现考虑可能的源编程语言中的以下源代码:
05:let super=BinaryTree(“root”,Empty,Empty);
06:super.left=root;
第05行创建“super”数据对象,作为上文所论述的BinaryTree<F>递归数据类型的实例。第06行设定“super”数据对象的left性质来引用在上述第00行处创建的“root”数据对象。在外观方法下,对于不支持隐式运行时解除分配的目标语言,第06行可能会在运行时导致“root”图形对象被导入到“super”图形对象中。此导入描绘于图5F中,图5F图解说明根据外观方法的在导入之后“super”、“root”及“left”数据对象的非循环表示。“root”及“left”外观对象已被更新以引用“super”图形对象。“super”图形对象及“super”映射对象被更新,以经由“root”数据对象的left性质(上述第02行)将“root”数据对象与“left”数据对象之间的关系映射到“root”关系对象。“super”图形对象及“super”映射对象也被更新,以经由“super”数据对象的left性质(上述第06行)将“super”对象与“root”数据对象之间的关系映射到“super”关系对象。请注意,即使第03行经编程以在没有外观方法的情况下创建引用循环,非循环性仍得以维持。
应注意的是,在上述第04行中被指派以引用“root”数据对象的“extra”外观对象在上述第06行所致使的图形导入之后可能仍引用“root”图形对象。然而,由于图形导入,“root”图形对象不再引用“root”关系对象。换句话说,“extra”外观对象已被上述第06行所导致的图形导入“放弃”了。此放弃描绘于图5F中。如可看出,“root”映射对象不再连接到“root”关系对象。因此,在上述第06行之后,源编程语言中的源代码的程序员可能需要注意不要试图使用“extra”外观对象将“root”数据对象与另一对象具有的关系解除引用。例如,考虑了以下额外源代码:
07:A=root.left;
08:B=extra.left;
在运行时,在图5F所描绘的导入之后,由于上述第02行的指派,结果将是变量A是引用“left”数据对象的外观对象。然而,第08行处的语句将生成运行时错误或故障,因为“extra”外观对象被图5F中所描绘的图形导入放弃。以源编程语言进行仔细编程可避免图形导入放弃的外观对象。例如,第04行处extra变量的创建可能会被省略,而是使用已创建的“root”外观对象。
引用同一底层数据对象及同一底层图形对象的不同外观对象无法基于外观对象的存储器地址的比较来恰当地进行相等性比较。这是因为外观对象存储在不同存储器地址处。然而,如果两个外观对象引用同一底层数据对象及同一底层图形对象,那么外观对象在语义上等于另一外观对象。根据外观方法,目标编程语言(例如,C或C++)中的相等运算符可被超驰,使得当比较两个外观对象相等时,如果其引用同一底层数据对象及同一底层图形对象,那么运算符指示其相等,而如果其引用不同数据对象或不同图形对象,那么运算符指示其不相等。
检查数据类型定义中的可能循环
如所提及,如果数据对象的集合在运行时从不含有引用循环,那么引用计数足以将数据对象及时解除分配。无需更复杂的解除分配机制,诸如垃圾收集或循环检测。
在运行时,其中数据对象形成的方式及其改变的方式是由源编程语言的源代码中的数据类型定义支配的。源编程语言可对源中的数据类型定义进行限制,所述限制足以防止在运行时出现引用循环。
例如,考虑可能的源编程语言中“Cons”列表的以下数据类型定义。Cons<F>数据类型是递归数据类型,其要么为空,要么具有头部元素及尾部元素,尾部元素是含有剩余元素的另一列表:
00:closed type List<E>;
01:closed concrete type Cons<F>extends List<F>{
02:head:F;
03:tail:List<F>;
04:}
05:closed concrete type Empty<G>extends List<G>{}
上述数据类型定义容易受到运行时引用循环的影响。例如,可通过创建Cons<F>数据对象来创建“ouroboros”列表,所述数据对象经配置以将其尾部指向自身,如在以下示例中:
06:let list=Cons(0,Empty);
07:list.tail=list;
根据技术中的一些,在源代码的编译时检测源编程语言的源代码中易受运行时引用循环影响的数据类型定义。然后,编译器可向程序员发出警示或暂停源代码的编译。例如,警示可以是用户接口或者到文件的输出中呈现的警告消息或错误消息。不是编译器检测源代码中的潜在引用循环并生成警示,而是专用类型检查工具或其它源代码管理工具可执行检测及发出警示。
一般来说,数据类型定义中潜在引用循环的检测涉及源编程语言编译器创建具有涉及的每一数据类型的节点的数据类型定义图形,且然后将每一性质的边添加到表示其数据类型的节点。对于泛型数据类型(诸如上述Cons<F>类型),编译器会将数据类型参数上下文化。上下文化是通过针对每一具体数据类型定义而不是抽象数据类型定义创建图形来完成的。具体数据类型定义可在运行时用于实例化所述数据类型的数据对象,而抽象数据类型定义仅用于支持从中派生的具体数据类型。利用根据具体数据类型定义的图形,编译器可将数据类型参数翻译成在具体数据类型定义上定义的那些参数的上下文,由此允许源编程语言中的源代码的程序员定义并安全地使用嵌套式数据结构,诸如例如列表中的列表。另外,对于每一数据类型参数,编译器都会创建“限制节点”来表示有关所述数据类型参数可能绑定到的数据类型的最坏情形。
图6A是如上文所定义的具体及泛型数据类型Cons<F>的示例性数据类型定义图形。图形中的实边线表示可能在运行时的引用循环中涉及的边。图形描绘了运行时引用循环可能出现的两种方式。
在第一种方式中,边602表示类型Cons<F>的数据对象可经由其尾部性质指向类型List<F>的数据对象。边604表示类型List<F>的数据对象也可以是类型Cons<F>的数据对象。
在第二种方式中,如果泛型数据类型F用正如Top的极泛型数据类型(其表示含有所有数据对象的假设超数据类型)来实例化,那么类型Cons<F>的数据对象可经由其头部性质指向类型F的数据对象,所述数据对象可能是某种未知数据类型,所述数据类型具有对类型Cons<F>的数据对象的其自身性质引用。第二种方式由图6A中的边606、608及610表示。
第一数据类型的引用循环可通过允许数据类型定义囊括额外的两条信息来解决。此信息可由源代码的程序员以源编程语言手动输入,基于源代码的静态分析来推断,或者自动添加到源代码,因为其是自动化或半自动化工具(诸如例如,自动或半自动数据类型检查工具)所需的。
如果数据对象的性质在运行时只能指向比含有所述性质的数据对象更旧的数据对象,那么所述性质不足以进行引用循环。因此,如果编译器可确定所述性质的初始值将比含有所述性质的数据对象更旧并且所述性质不能从其初始值改变(例如,是只读的),那么所述性质不足以进行引用循环。
根据所述技术,可在数据对象的数据类型定义中隐式地(例如,默认地)或显式地(例如,由程序员)对数据对象的性质定义两个元性质:
·只读–“只读”性质是无法从其最初指派的值改变的数据对象的性质。
·早期–“早期”性质是在对含有所述性质的数据对象的任何引用用作值之前确定最初指派的值的数据对象的性质,而不是仅仅用作将数据对象的性质初始化的方法。后一种限定避免了构造符中的边缘情形。
在具有上述两个元性质的情况下,可使用以下只读及早期提示来修改上述示例性数据类型定义,如以下示例所示:
00:closed type List<E>;
01:closed concrete type Cons<F>extends List<F>{
02:head:F;
03:readonly early tail:List<F>;
04:}
05:closed concrete type Empty<G>extends List<G>{}
编译器可通过多种方式在编译时确定数据类型定义的性质是否为只读。无需特定方式。一种方式是基于程序员在性质定义中显式地编程的关键字提示。关键字提示可以是“const”、“final”、“readonly”等等。另一方式可基于不存在具有相反含义的关键字提示,诸如例如,在性质定义中不存在“mutable”或“writeable”关键字提示。又一方式是编译器对源代码进行静态分析,以确定可将性质设定为值的源代码中的任一者在指派初始值之后实际上是否这样做。如果不是,那么编译器可推断所述性质是只读的。静态分析可通过性质定义中的显式关键字提示(例如,“read-only”)来触发。
编译器还可通过在编译时插入额外指令来强制性质为只读的,以防止在性质已被初始化之后在运行时为所述性质指派值。另外或另一选择是,额外指令可记录(例如,在运行时诊断日志或运行时剖析器日志中)在所述性质已被初始化之后为所述性质指派值的任何运行时尝试。
同样地,编译器可通过多种方式在编译时确定所述性质是否为早期的。无需特定方式。一种方式是基于性质定义中存在或不存在关键字提示。另一方式是编译器静态地分析源代码,以确定在对含有数据对象的任何引用作为值之前是否已将所述性质初始化。静态分析可通过性质定义中的显式关键字提示(例如,“early”)来触发。
编译器还可通过在编译时插入额外指令来强制性质为早期的,以防止在对含有所述性质的数据对象的引用用作值之后在运行时将所述性质初始化。另外或另一选择是,额外指令可记录(例如,在运行时诊断日志或运行时剖析器日志中)在对含有性质的数据对象的引用被用作值之后在运行时将运行时性质初始化的任何尝试。
编译器还可通过各种方式在编译时确定数据类型是否是封闭的。封闭式数据类型是编译器在编译时已知其任何及所有子数据类型的数据类型。编译器可基于数据类型定义中的显式关键字提示(诸如“final”、“close”、“sealed”等等)或基于数据类型定义中具有相反含义的显式关键字提示(诸如“open”等等)来确定数据类型是封闭的。封闭性也可由编译器基于上下文来推断作为源代码静态分析的一部分。例如,如果对数据类型定义的访问由信息隐藏机制限制到一些模块或包,并且那些模块或包中不存在所述数据类型的子数据类型的定义,那么编译器可推断所述数据类型是封闭的。
编译器还可通过各种方式在编译时确定数据类型是否是具体的。具体数据类型是可作为那种类型的数据对象存在的数据类型,所述数据对象不是所述数据类型的子数据类型的实例。具体数据类型与抽象数据类型形成对比,所述抽象数据类型不足以定义数据对象,但可从中派生具体子数据类型。编译器可基于数据类型定义中存在显式关键字提示(诸如“concrete”)或基于数据类型定义中存在具有相反含义的显式关键字提示(诸如“abstract”)来确定数据类型是具体的。编译器可通过源代码的静态分析来推断数据类型的具体性,诸如在源代码中使用数据类型来构造所述数据类型的数据对象,或者通过在源代码中的数据类型的数据类型定义中不存在将防止构造所述数据类型的数据对象的定义元素。由于所有数据对象都必须是具体数据类型,因此仅对针对潜在创建引用循环的具体数据类型进行类型检查就足够了。
图6B是使用只读及早期提示的上述示例性数据类型定义的示例性数据类型定义图形。如可看到,边602及604现被断开以反映对应引用不能参与运行时引用循环的创建。另外,尾部性质的边602现具有小于或等于关系(‘<=’)而不是严格小于关系(‘<’)。语义上,如果数据类型定义图形中的循环中的边具有小于或等于关系(‘<=’),那么存在使由边表示的数据类型定义部分不足以进行运行时引用循环的已知规则。一种类型的已知规则是只读早期关系。例如,由于对尾部性质的只读及早期限制,图6A中的边602及604的潜在引用循环不再是如图6B中所表示的潜在引用循环。应认识到,断言数据类型小于或等于其自身并不矛盾。
然而,仍存在由图6B中的边606、608及610表示的潜在引用循环。特定来说,即使对尾部性质有只读及早期提示,Cons<F>数据对象的头部性质仍可引用未知类型F的数据对象,而所述数据对象又往回可指向Cons<F>数据对象,由此创建引用循环。即使头部性质是只读及早期的,情况也会如此,因为头部性质可能会被初始化为未知类型F的数据对象,而所述数据对象又引用Cons<F>数据对象。
在防止由图6B中的边606、608及610表示的引用循环类型中,可期望允许特定数据类型的数据对象引用同一特定数据类型的另一数据对象,只要所述引用不是针对其自身。例如,应允许不引用自身的列表中的列表。此外,应允许含有原始数据类型的数据对象。例如,应允许字符串或数字列表。
为了解决如同数据对象的性质是可以是任何数据类型的泛型数据类型的问题,可使用以源编程语言中的源代码表达的额外限制。例如,考虑了“Cons”列表的以下数据类型定义:
00:closed type List<ECons<E>>;
01:closed concrete type Cons<FCons<F>>extends List<F>{
02:head:F;
03:readonly early tail:List<F>;
04:}
05:closed concrete type Empty<GCons<G>>extends List<G>{}
在上述示例中,标记AB意指A类型数据对象不得在运行时直接引用B类型数据对象或直接引用任何直接引用B类型数据对象的数据对象。例如,在决定List<Number>是否有效时,所述技术遵循此标记法。所述标记可写为破折号竖条,并且符号可在源编程语言中的源中显示为/>或('-|'),具体取决于源代码编辑器中使用的字体连字。可使用其它基于文本的标记来表达A不能指向B的限制,并且本发明不限于破折号竖条标记。
根据所述技术,上述数据类型定义的结果是Cons<F>的数据类型定义是泛型的、递归的,并且重要的是,无引用循环。
图6C是使用只读及早期提示以及额外限制的上述示例性数据类型定义的示例性数据类型定义图形。如可看到,数据类型定义不存在涉及从Cons<F>回到Cons<F>的‘<’边的潜在引用循环(以从Cons<F>的引用开始)。图6B的数据类型定义图形与图6C的数据类型定义图形之间的不同之处在于F数据对象可以是而不是/>由于那种限制,不存在与Top(即,所有内容的超数据类型)或List<F>或Cons<F>的“may-be”连接。然而,允许使用Empty<F>(其不引用任何内容)。
示例性数据类型检查过程
图7A、图7B、图7C、图7D、图7E、图7F、图7G、图7H囊括示例性数据类型检查过程的流程图。数据类型检查过程可由源编程语言中的源代码的编译器来执行,其中源代码含有具体数据类型定义。编译器可执行数据类型检查过程以确定具体数据类型定义是否允许运行时引用循环。在检测到允许运行时引用循环的具体数据类型定义之后,编译器可即刻暂停编译过程或输出警示。警示可被输出到用户接口(例如,图形或命令行)、文件、数据库、或用于警示的另一适合数据容器。警示可以是指示由类型检查过程识别的具体类型定义存在问题的错误或警告消息。例如,消息可识别允许运行时引用循环的具体数据类型定义。例如,识别可囊括源代码文件的名称及源代码文件中的行编号,或者定义了具体数据类型定义的源代码文件中的行编号集或行编号范围,连同错误或警告的解释。例如,解释可能会陈述正如“第52行处的mysource.src中所定义的具体类型Cons<F>允许引用循环”的内容。
执行类型检查过程的编译器可以是将源编程语言中的源代码编译为一种或多种目标编程语言的源到源编译器,其中一种或多种目标编程语言包含具有对解除分配的最小运行时支持(例如,无隐式解除分配服务)的至少一种目标编程语言。例如,目标编程语言可以是C、C++、OBJECTIVE-C或RUST中的任一种。另一选择是,源代码的编译器可为了质量控制的目的来处理源代码,而不另外将源代码的中间表示翻译为目标编程语言。作为又一替代方案,编译器可以是将源编程语言中的源代码编译为一种或多种目标编程语言的源到源编译器,其中所有目标语言都支持隐式解除分配。在此情形中,可执行类型检查以进行质量控制,诸如例如以减少或消除对运行时垃圾收集或循环检测的需要。
以图7A开始,数据类型检查过程以源代码中所定义的具体数据类型C的数据类型检查图形的未经构建节点的空列表开始712。空列表可以是在计算机存储介质中被初始化的适合列表数据结构。作为工作示例,对数据类型检查过程的解释将使用以可能的源编程语言表达的以下数据类型定义:
00:closed type List<ECons<E>>;
01:closed concrete type Cons<FCons<F>>extends List<F>{
02:head:F;
03:readonly early tail:List<F>;
04:}
05:closed concrete type Empty<GCons<G>>extends List<G>{}
在工作示例中,C是具体数据类型Cons<F>。
在操作714处,将表示图形中具体数据类型C的节点的元素添加到未经构建节点列表。在工作示例中,表示具体数据类型Cons<F>的节点的元素可被添加到未经构建节点列表。
在操作716处,确定未经构建节点列表是否为空(即,未含有任何元素)。如果未经构建节点列表不为空,那么针对未经构建节点列表上的当前节点执行操作718、720、722及724。
在操作718处,识别未经构建节点列表上的当前节点N。例如,当前节点N可以是与最近最少添加到未经构建节点列表的元素对应的节点。在工作示例中,当前节点N可以是针对具体数据类型Cons<F>来添加的节点。
在操作720处,从未经构建节点列表移除表示当前节点N的元素。在工作示例中,表示具体数据类型Cons<F>的当前节点N的元素可从未经构建节点列表移除。
对源代码中所定义的扩展由当前节点N表示的数据类型的每一直接子数据类型S执行操作722。子数据类型可在子类(sub class或child class)意义上直接扩展由当前节点N表示的数据类型,这通常是支持基于特质的继承的面向对象的编程语言所允许的。源编程语言可支持此种基于特质的继承。特质提供了细粒度代码再次使用的机制。特质可被定义为独立于任何类层次结构的一组方法,且可通过一组组合操作灵活地用于构建其它特质或类。
参考图7B更详细地描述操作722。在工作示例中,当当前节点N针对Cons<F>数据类型时,可不对具体数据类型Cons<F>的任何直接子数据类型S执行操作722,因为没有定义扩展Cons<F>数据类型的直接子数据类型。
对由当前节点N表示的数据类型的每一性质P执行操作724。所述数据类型的性质[AS12]可对应于由当前节点N表示的数据类型的定义的源代码中的成员变量定义。所述成员变量可以是所述数据类型的静态变量或实例变量。关于图7C更详细地描述操作724。在工作示例中,可针对为Cons<F>数据类型定义的头部性质及尾部性质中的每一者来执行操作724。
在对当前节点N执行操作718、720、722及724之后,过程返回到操作716以考虑未经构建节点列表上与其它节点对应的任何剩余元素。如果在操作716处未经构建节点列表上不存在剩余元素,那么在操作726处,将在操作720处移除的所有节点的元素往回添加到未经构建节点列表上以用于进一步处理,如下文关于图7D所描述。
如所提及,图7A的操作722是针对源代码中的每一子数据类型S执行的,其直接扩展由当前节点N表示的数据类型。图7B是操作722的流程图。
在操作728处,如果当前直接子数据类型S是泛型类型,那么使用由当前节点N表示的数据类型的类型参数来翻译当前直接子数据类型S。例如,在给定诸如“class Sub<X>extends Super<Bar<X>>”的类型关系及诸如“Super<Bar<Baz>>”的超类型的情况下,翻译可包含为子类型参数中的每一者找到适当绑定。在此示例中,X将绑定到Baz,并且经翻译子数据类型将为Sub<Baz>,因为Sub<Baz>扩展了Super<Bar<Baz>>,这是已知的,因为Sub<X>扩展了Super<Bar<X>>镜像,当X被替换为Baz时,且X上没有任何绑定,这会防止X绑定到Baz。
在操作730处,确定表示当前直接子数据类型S的节点的元素是否在未经构建节点列表上。如果不是,那么在操作732处,为表示当前直接子数据类型S的节点创建元素,并且在操作734处,将所述元素添加到未经构建节点列表。在任一情形中,将边添加736到具体数据类型C的数据类型定义图形,其中所述边是从当前节点N到当前直接子数据类型S的节点。所述边符合“may-be”要求,因为作为由当前节点N表示的数据类型的实例的数据对象也可以是当前直接子数据类型S的实例。
如所提及,图7A的操作724是针对如由源代码中所定义的当前节点N表示的数据类型的每一性质P来执行的。图7C是操作724的流程图。在工作示例中,如果当前节点N表示Cons<F>数据类型,那么针对头部性质及尾部性质中的每一者来执行操作724。
在操作738处,使用由当前节点N表示的数据类型的类型参数来翻译当前性质P的数据类型。在工作示例中,当当前性质P是Cons<F>数据类型的头部性质时,那么当前性质P的数据类型是泛型类型F。当当前性质是Cons<F>数据类型的尾部性质时,那么当前性质P的数据类型是List<F>。
在操作740处,确定表示当前性质P的数据类型的节点的元素是否在未经构建节点列表上。如果不是,那么在操作742处,为表示当前性质P的数据类型的节点创建元素。在操作744处,将所述元素添加到未经构建节点列表。在工作示例中,当当前性质P是Cons<F>数据类型的头部性质时,那么将表示泛型数据类型F的图形中的节点的元素添加到未经构建节点列表。当当前性质P是Cons<F>数据类型的尾部性质时,那么将表示List<F>数据类型的图形中的节点的元素添加到未经构建节点列表。
在操作746处,当前性质P是否被定义为只读及早期的。在工作示例中,当当前性质P是Cons<F>数据类型的头部性质时,那么可通过Cons<F>数据类型的数据类型定义的性质定义中缺少此类关键字提示来确定当前性质P并非只读及早期的。另一方面,当当前性质P是Cons<F>数据类型的尾部性质时,可通过Cons<F>数据类型的尾部性质的性质定义中存在此类关键字提示来确定当前性质P是只读及早期的。
在操作748处,如果当前性质P是只读及早期的,那么将边添加到具体数据类型C的数据类型定义图形,其中所述边是从当前节点N到表示当前性质P的数据类型的节点。所述边符合“<=”要求。在工作示例中,当当前性质P是Cons<F>数据类型的尾部性质时,由于尾部性质是只读及早期的,因此具有“<=”要求的从表示Cons<F>数据类型的节点到表示List<F>数据类型的节点的边将被添加。
在操作750处,如果当前性质P并非只读及早期的,那么将边添加到具体数据类型C的数据类型定义图形,其中所述边是从当前节点N到表示当前性质P的数据类型的节点。在这种情况下,所述边符合“<”要求。在工作示例中,当当前性质P是Cons<F>数据类型的头部性质时,由于头部性质并非只读及早期的,因此具有“<”要求的从表示Cons<F>数据类型的节点到表示F数据类型的节点的边将被添加。
在工作示例中,在对Cons<F>数据类型的头部性质及尾部性质执行操作724之后,所述过程返回到操作716以确定未经构建节点列表是否为空。由于泛型数据类型F及List<F>数据类型的元素已添加到未经构建节点列表,因此所述列表不为空。在操作720处,这些节点将从列表移除。操作722将由Lit<F>数据类型执行,因为其具有扩展List<F>数据类型的直接子数据类型Empty<F>。将不对泛型数据类型F执行操作722,因为不存在扩展泛型数据类型F的直接子数据类型。将不对泛型数据类型F或List<F>数据类型执行操作724,因为不存在那些数据类型的已定义性质。作为对List<F>数据类型执行操作722的结果,Empty<F>数据类型的节点将被添加到图形(操作734),并且具有“may-be”要求的从List<F>数据类型的节点到Empty<F>数据类型的新节点(操作736)的边被添加。当过程再次返回到操作716时,那么仅表示Empty<F>数据类型的节点的元素位于未经构建节点列表上。所述元素将在操作720处被移除,并且不会对所述节点执行操作722及724,因为Empty<F>数据类型不具有扩展其的任何直接子数据类型或任何所定义性质。
现参考图7D,在根据图7A、图7B及图7C的子过程来构建的所有节点的元素已被往回添加到未经构建节点列表之后,针对具体数据类型C的数据类型检查过程继续从图7A的操作726得到的未经构建节点列表。在工作示例中,过程中此时存在以下数据类型的节点:Empty<F>、List<F>、F及Cons<F>。那些节点的元素将往回被添加到未经构建节点列表。
在操作752处,确定未经构建节点列表是否为空(即,未含有任何元素)。如果未经构建节点列表不为空,那么针对未经构建节点列表上的当前节点执行操作754、756及758以构建节点。
在操作754处,识别未经构建节点列表上的当前节点N。例如,当前节点N可以是与最近最少添加到未经构建节点列表的元素对应的节点。
在操作756处,从未经构建节点列表移除表示当前节点N的元素。
操作760、762、764、766及768可针对由当前节点N表示的数据类型直接扩展自的每一超数据类型来执行,如源代码中所定义。由当前节点N表示的数据类型可直接扩展超类或父类意义上的超数据类型,如通常是支持基于特质的继承的面向对象的编程语言所允许的。源编程语言可支持基于特质的继承。
为了操作760、762、764、766及768的目的,如果表示当前节点N的数据类型不直接扩展如源代码中所定义的超数据类型,那么所述数据类型被认为直接扩展表示每个其它数据类型的假设超数据类型的假设“Top”超数据类型。这样一来,针对被认为直接扩展Top超数据类型的每一当前节点N来至少执行操作768,并且针对Top超数据类型来各自执行操作746及766一次。
在操作760处,如果当前直接超类型T是泛型类型,那么使用由当前节点N表示的数据类型的类型参数来翻译当前直接超数据类型T。
在操作762处,确定表示当前直接超数据类型T的节点的元素是否在未经构建节点列表上。如果不是,那么在操作764处,为表示当前直接超数据类型T的节点创建元素,并且在操作766处,将所述元素添加到未经构建节点列表。在任一情形中,在操作768处,将边添加到具体数据类型C的数据类型定义图形中,其中所述边是从当前直接超数据类型T的节点到当前节点N。所述边符合“may-be”要求,因为作为当前直接超数据类型T的实例的数据对象也可以是由当前节点N表示的数据类型的实例。
在对当前节点N执行操作754、756及758之后,过程返回到操作752以考虑未经构建节点列表上与其它节点对应的任何剩余元素。如果在操作752处在未经构建节点列表上不存在剩余元素,那么由图7D的流程图描绘的子过程结束。
在工作示例中,作为Cons<F>数据类型的超数据类型的List<F>的节点已存在于具体数据类型Cons<F>的图形中。在操作768处,将具有“may-be”要求的从List<F>的节点到Cons<F>数据类型的节点的边添加到图形。List<F>数据类型也是Empty<F>数据类型的超数据类型。然而,在图7B的操作736处,当考虑扩展List<F>数据类型的直接子数据类型时,具有“may-be”要求的从List<F>的节点到Empty<F>数据类型的节点的边已被添加。因此,无需在操作768处再次添加。此外,在操作768处,具有“may-be”要求的从Top超数据类型的everything节点到表示泛型数据类型F的节点的边也被添加。类似地,在操作768处,具有“may-be”要求的从Top超数据类型节点到表示List<F>泛用数据类型的节点的边被添加。
现参考图7E,具体数据类型C的数据类型检查过程继续具体数据类型C的数据类型定义图形的节点及边,因为其在对具体数据类型C执行由图7A、图7B、图7C及图7D的流程图描绘的子过程之后存在。
就这一点来说,在具体数据类型C的图形的构造中,所述图形由数据类型节点而非限制节点构成。图形中的数据类型节点是基于具体数据类型C的直接子数据类型、具体数据C的性质的数据类型以及那些直接子数据类型、那些性质数据类型及具体数据类型C的超数据类型来创建的,如上文关于图7A、图7B、图7C及图7D所描述。
限制节点可由编译器添加到具体数据类型C的数据类型定义图形,以对非限制数据类型节点进行分组。此上下文中的非限制数据类型节点是表示作为以下各项的数据类型的节点:(a)非封闭式数据类型,即并非所有子数据类型在编译时都为编译器所知;或者(b)泛型数据类型。
可针对图形中作为数据类型节点的每一节点来执行操作770。在操作772处,确定由当前数据类型节点N表示的数据类型是否是非限制的。如果为否,那么不对当前数据类型节点N执行操作774、776、778及780。如果为是,那么对当前数据类型节点N执行操作774、776、778及780。在工作示例中,Top、Empty<F>、List<F>、F及Cons<F>数据类型的节点是图形的数据类型节点。其中,Empty<F>、List<F>、F及Cons<F>数据类型的节点是非限制的,因为那些数据类型是泛型数据类型。
在操作774处,确定作为由当前数据类型节点N表示的数据类型的经翻译超数据类型的“YES”数据类型集。
在操作776处,确定对由当前数据类型节点N表示的数据类型的不可引用限制的“NO”集。
在操作778处,如果针对当前YES集及当前NO集的组合还没有将限制节点LN添加到具体数据类型C的图形中,那么针对组合创建限制节点LN并将其添加到图形。
在操作780处,将具有“may-be”要求的从表示当前数据类型的节点N到当前YES及NO组合的限制节点LN的边添加到图形中。
现参考图7F,具体数据类型C的数据类型检查过程继续具体数据类型C的数据类型定义图形的节点及边,因为其在对具体数据类型C执行由图7A、图7B、图7C、图7D及图7E的流程图描绘的子过程之后存在。
针对图形中的每一限制节点执行操作782。并且对于图形中的每一限制节点,针对图形中的每一数据类型节点来执行操作784。
在操作786处,确定当前节点N的数据类型是否是当前限制节点LN的YES集(图7E的操作774)中的每一数据类型的子数据类型。如果这样,那么过程行进到操作788。如果为否,那么图7F的子过程结束。
在操作788处,确定当前限制节点LN的NO集(图7E的操作776)中的任何数据类型是否是当前节点N的数据类型的子数据类型。如果为是,那么图7F的子过程结束。否则,在操作790处,在图形中创建从当前限制节点LN到当前数据类型节点N的具有小于‘<’要求的边。
现参考图7G,具体数据类型C的数据类型检查过程继续具体数据类型C的数据类型定义图形的节点及边,因为其在对具体数据类型C执行由图7A、图7B、图7C、图7D、图7E及图7F的流程图描绘的子过程之后存在。
在操作792处,集CHAIN被初始化为空边集。
在操作794处,集VISITED被初始化为空节点集。
在操作796处,从根据图7A、图7B、图7C、图7D、图7E及图7F的子过程来生成数据类型定义图形的具体数据类型C开始调用子过程。所述子过程寻找图形中的矛盾并在下文关于图7H进行更详细解释。
在操作798处,报告在类型检查过程期间检测到的任何问题。例如,对于在以源编程语言写入的源代码中识别的每一潜在引用循环,可提供输出到诸如命令行接口或图形用户接口等计算机用户接口或者输出到提供潜在引用循环的人类可读描述的文件或数据库。输出可以是文本,诸如例如“类型‘Thing’的值可通过其性质‘otherThing’引用自身。'aThing.otherThing=aThing;'将创建引用循环。”输出可从与检测到潜在引用循环的具体数据类型C的数据类型定义图形的节点或边相关联的元数据派生。输出还可建议如何纠正问题,例如避免潜在引用循环。输出可被输入到集成式开发环境(IDE)程序,以自动地或者基于人类程序员选择或批准的建议来改变源代码。
现参考图7H,其是在图7G的子过程的操作796处调用的查找矛盾子过程的流程图。使用当前节点N来调用子过程。子过程也可以是递归的或以非递归但等效方式实施。对于查找矛盾子过程的第一调用,当前节点N是图形中表示为其生成数据类型定义图形的具体数据类型C的节点。
在操作800处,确定当前节点N是否在VISITED集中。如果当前节点N在VISITED集中,那么查找矛盾子过程行进到操作802。
在操作802处,确定CHAIN集是否含有具有‘<’要求的边。如果是,那么子过程行进到操作804。
在操作804处,报告具体数据类型C的潜在引用循环问题。例如,可使用CHAIN集中的边集以派生出问题的人类可读解释来报告问题。
如果在操作802处,CHAIN集中不存在具有‘<’要求的边,那么在操作806处,从VISITED集移除当前节点N,并且查找矛盾子过程的当前调用返回/结束。
如果在操作800处如果当前节点N不在VISITED集中,那么在操作808处将当前节点N添加到VISITED集。
针对从当前节点N的图形中的每一边执行操作810。
在操作812处,如果CHAIN集为空或者如果当前边E具有‘<’或‘<=’要求,那么在操作814处,当前边E被添加到CHAIN集,递归地调用816查找矛盾子过程,从而提供具有当前边E的图形中的目标节点作为递归调用的输入节点,并且当递归调用返回/结束时,在行进到操作806之前当前边E被从CHAIN集的端移除818。如果在操作812处,CHAIN不为空或者如果当前边E不具有‘<’或‘<=’要求,那么子过程行进到操作806。
益处
可证明的非循环对象有若干益处。一方面,进行引用计数足以将运行时对象及时解除分配。另一方面,某些运行时元操作变得简化且更可靠,其包含:
·比较两个运行时对象,以找出其在结构上是否相同(即,确定两个对象是同一类型的对象,其对应性质本身在结构上是等效的),
·派生运行时对象的指纹,所述指纹独立于其各部分如何布置在存储器中,
·将对象序列化以传输到另一计算过程或计算机,以及
·将对象转换为可展示给正在调试问题的人类程序员的诊断形式。
无引用循环的数据类型定义在分布式计算系统中也有益处。例如,当许多性质值与含有性质值的对象位于系统的不同计算节点上时,分布式垃圾收集可能需要在分布式计算过程之间来回进行大量过程间通信(例如,数据网络)消息传送。另一方面,如果所有数据类型都是非循环的,那么分布式垃圾收集可用分布式引用计数代替,并且引用计数更新可以批量化为更少的更小消息,所述消息可在系统中的节点处执行,其中节点处的计算过程等待的时间更少。
基本计算装置
所述技术可由至少一个计算装置来实施。如果通过不止一个计算装置来实施,那么所述技术可使用使用诸如分组数据网络的网络耦合在一起的计算装置的组合来整体或部分地实施。在所述技术的实施方式中使用的计算装置可以是硬连线的,以执行所述技术中的一些或全部,或者可包含诸如至少一个专用集成电路(ASIC)或现场可编程门阵列(FPGA)的数字电子装置,其经持久编程以执行所述技术中的一些或全部,或者可包含至少一个一般用途硬件处理器,其经编程以便以固件、存储器、其它存储装置或其组合中的程序指令来执行所述技术中的一些或全部。在所述技术的实施方式中使用的计算装置也可将定制硬连线逻辑、ASIC或FPGA与定制编程组合,以完成所述技术中的一些或全部。在所述技术的实施方式中使用的计算装置可以是服务器计算装置、工作站计算装置、个人计算装置、可携式计算装置、手持式计算装置、移动计算装置或者并入有硬连线或程序逻辑来实施所述技术中的一些或全部的任何其它计算装置。
图8是可在技术的实施方式中使用的示例性基本计算装置的框图。在图8的示例中,计算装置800及用于以硬件、软件或硬件与软件的组合实施一些或所有技术的指令被示意性地表示为例如方框及圆圈,其详细程度与本公开所属领域的普通技术人员通常用于传递关于计算机架构及计算装置实施方式的详细程度相同。
计算装置800包含输入/输出(I/O)子系统802,所述子系统可包含总线或其它通信机制,用于通过电子信号路径在计算装置800的组件之间传递信息或指令。I/O子系统802可包含I/O控制器、存储器控制器及至少一个I/O端口。电子信号路径在图式中示意性地表示为例如线、单向箭头或双向箭头。
至少一个硬件处理器804耦合到I/O子系统802,以用于处理信息及指令。硬件处理器804可包含例如一般用途微处理器或微控制器或特殊用途微处理器,诸如嵌入式系统或图形处理单元(GPU)或者数字信号处理器或ARM处理器。处理器804可包括集成算术逻辑单元(ALU)或者可耦合到单独ALU。
计算装置800包含一个或多个存储器单元806,诸如主存储器,其耦合到I/O子系统802,以用于电子数字地存储数据及将由处理器804执行的指令。存储器806可包含易失性存储器,诸如各种形式的随机存取存储器(RAM)或其它动态存储装置。存储器806还可用于在处理器804执行指令期间存储临时变量或其它中间信息。当存储在处理器804可访问的非暂时性存储介质中时,此类指令可使计算装置800成为特定用途机器,所述特定用途机器经定制以执行指令中所规定的操作。
计算装置800进一步包含耦合到I/O子系统802的非易失性存储器,诸如只读存储器(ROM)808或其它静态存储装置,以用于存储用于处理器804的信息及指令。ROM 808可包含各种形式的可编程ROM(PROM),诸如可擦除PROM(EPROM)或电可擦除PROM(EEPROM)。永久存储装置单元810可包含各种形式的非易失性RAM(NVRAM),诸如FLASH存储器或固态存储装置、磁盘或光盘(诸如CD-ROM或DVD-ROM),并且可耦合到I/O子系统802以存储信息及指令。存储装置810是可用于存储指令及数据的非暂时性计算机可读介质的示例,当由处理器804执行时,所述指令及数据致使执行计算机实施方法来执行一些或所有所述技术。
存储器806、ROM 808或存储装置810中的指令可包括一组或多组指令,所述指令被组织为模块、方法、对象、函数、例程或叫用。所述指令可被组织为一个或多个计算机程序、操作系统服务或包含移动app的应用程序。指令可包括操作系统或系统软件;支持多介质、编程或其它功能的一个或多个库;实施TCP/IP、HTTP或其它通信协议的数据协议指令或堆栈;解释并再现使用HTML、XML、JPEG、MPEG或PNG来编码的文件的文件处理指令;为图形用户接口(GUI)、命令行接口或文本用户接口再现或解释命令的用户接口指令;应用软件,诸如办公套件、互联网接入应用、设计及制造应用、图形应用、音频应用、软件工程应用、教育应用、游戏或各种应用。所述指令可实施web服务器、web应用服务器或web客户端。指令可被组织为呈现层、应用层及数据存储层,诸如使用结构化查询语言(SQL)或NoSQL的关系数据库系统、对象存储区、图形数据库、平面文件系统或其它数据存储装置。
计算装置800可经由I/O子系统802耦合到至少一个输出装置812。输出装置812可以是数字计算机显示器。可使用的显示器的示例包含触摸屏显示器或发光二极管(LED)显示器或液晶显示器(LCD)或电子纸显示器。作为显示装置的替代或补充,计算装置800可包含其它类型的输出装置812。其它输出装置812的示例包含打印机、票据打印机、绘图仪、投影仪、声卡或视频卡、扬声器、蜂鸣器或压电装置或其它听觉装置、灯或LED或LCD指示器、触觉装置、致动器或伺服系统。
输入装置814可耦合到I/O子系统802,用于将信号、数据、命令选择或手势传递给处理器804。输入装置814的示例包含触摸屏、传声器、静态及视频数码相机、字母数字键及其它键、小键盘、键盘、图形输入板、图像扫描仪、操纵杆、时钟、开关、按钮、拨号盘、滑块或各种类型的传感器,诸如力传感器、运动传感器、热传感器、加速度计、陀螺仪及惯性测量单元(IMU)传感器,或者各种类型的收发器,诸如无线收发器,诸如蜂窝式或Wi-Fi、射频(RF)或红外(IR)收发器及全球定位系统(GPS)收发器。
另一类型的输入装置是控制装置816,其可执行光标控制或其它自动控制功能,诸如在显示屏上的图形接口中导航,作为输入功能的替代或补充。控制装置816可以是触摸板、鼠标、轨迹球或光标方向键,以用于将方向信息及命令选择传递给处理器804,并用于控制显示器812上的光标移动。输入装置可在两根轴线(第一轴线(例如,x)及第二轴线(例如,y))上具有至少两个自由度,这允许装置规定平面中的位置。另一类型的输入装置是有线、无线或光学控制装置,诸如操纵杆、棒、控制台、方向盘、踏板、换档机构或其它类型的控制装置。输入装置814可包含多个不同输入装置的组合,诸如摄像机及深度传感器。
计算装置800可包括物联网(IoT)装置或其它计算器具,其中省略了输出装置812、输入装置814及控制装置816中的一者或多者。输入装置814可包括一个或多个相机、运动检测器、温度计、传声器、地震检测器、其它传感器或检测器、测量装置或编码器,并且输出装置812可包括特殊用途显示器,诸如单线LED或LCD显示器、一个或多个指示器、显示面板、仪表、阀门、螺线管、致动器或伺服机构。
当计算装置800是移动或可携式计算装置时,输入装置814可包括耦合到GPS模块的全球定位系统(GPS)接收器,所述GPS模块能够对多个GPS卫星进行三角测量,确定并生成地理位置或位置数据,诸如计算装置800的地球物理位置的经纬度值。输出装置812可包含硬件、软件、固件及接口,用于生成朝向主机824或服务器830引导的位置报告分组、通知、脉冲或心跳信号,或者规定计算装置800的位置的其它循环数据传输,单独地或与其它特殊用途数据组合。
计算装置800可使用所定制硬连线逻辑、至少一个ASIC或FPGA、固件或程序指令或逻辑来实施所述技术中的一些或全部,所述指令或逻辑在与计算装置800组合地被加载及使用或执行时致使或编程计算装置800作为特殊用途机器来操作。
由计算装置800执行的技术可响应于处理器804执行主存储器806中所含有的至少一个指令的至少一个序列来执行。此类指令可从另一存储介质(诸如存储装置810)读入主存储器806。主存储器806中所含有的指令序列的执行致使处理器804执行一些或所有技术。可使用硬连线电路系统来代替软件指令或者与软件指令组合。
本文中所使用的术语“存储介质”是指存储致使机器以特定方式运行的数据或指令的任何非暂时性计算机可读介质。此种存储介质可包括非易失性介质或易失性介质。例如,非易失性介质包含光盘或磁盘,诸如存储装置810。易失性介质包含动态存储器,诸如存储器806。存储介质的通用形式包含例如硬盘、固态驱动器、快闪驱动器、磁性数据存储介质、任何光学或物理数据存储介质、存储器芯片等等。
存储介质相异于传输介质但可与传输介质结合使用。传输介质参与存储介质之间的信息传送。例如,传输介质包含同轴电缆、铜线及光纤,从而包含包括I/O子系统802的总线的线。传输介质也可采用声波或者光波的形式,诸如在无线电波及红外数据通信期间生成的那些。
各种形式的介质可涉及将至少一个指令的至少一个序列载送到处理器804以供执行。例如,指令最初可由远程计算机的磁盘或固态驱动器载送。远程计算机可将指令加载到其动态存储器中,并使用调制解调器通过诸如光纤或同轴电缆或电话线的通信链路发送指令。计算装置800本地的调制解调器或路由器可接收通信链路上的数据,并转换数据以供计算装置800读取。例如,诸如射频天线或红外线检测器的接收器可接收无线或光学信号中载送的数据,并且适当电路系统可将数据提供给I/O子系统802,诸如将数据放置在总线上。I/O子系统802将数据载送到存储器806,处理器804从存储器806检索并执行指令。由存储器806接收的指令可以可选地在由处理器804执行之前或之后存储在存储装置810上。
计算装置800还包含耦合到总线802的通信接口818。通信接口818提供耦合到网络链路820的双向数据通信,网络链路820直接或间接连接到至少一个通信网络,诸如网络822或互联网上的公共或私有云。例如,通信接口818可以是以太网网络接口、综合业务数字网络(ISDN)卡、电缆调制解调器、卫星调制解调器或调制解调器,以提供到对应类型的通信线路的数据通信连接,例如以太网电缆或任何种类的金属电缆或光纤线路或电话线。网络822广义地表示局域网(LAN)、广域网(WAN)、校园网、互联网或其任一组合。通信接口818可包括LAN卡,以提供到兼容LAN的数据通信连接,或者有线发送或接收根据蜂窝式无线电话无线网络标准的蜂窝式无线电话接口,或者有线发送或接收根据卫星无线网络标准的数字数据的卫星无线电接口。在任何此种实施方案中,通信接口618通过载送表示各种类型的信息的数字数据流的信号路径发送及接收电、电磁或光学信号。
网络链路820通常使用例如卫星、蜂窝、Wi-Fi或蓝牙技术直接或通过至少一个网络将电、电磁或光学数据通信提供给其它数据装置。例如,网络链路820可通过网络822提供到主机计算机824的连接。
此外,网络链路820可通过网络822提供连接,或者经由由互联网服务提供商(ISP)826操作的互联装置及/或计算机提供到其它计算装置的连接。ISP 826通过表示为互联网828的全球分组数据通信网络提供数据通信服务。服务器计算机830可耦合到互联网828。服务器830广义地表示具有或不具有管理程序的任何计算机、数据中心、虚拟机或虚拟计算实例,或者执行例如DOCKER或KUBERNETES的容器化程序系统的计算机。服务器830可表示使用不止一个计算机或实例来实施并通过传输web服务请求、在HTTP有效载荷中具有参数的统一资源定位符(URL)字符串、API叫、app服务叫用或其它服务叫用来访问及使用的电子数字服务。
计算装置800及服务器830可形成分布式计算系统的元件,所述分布式计算系统包含其它计算机、处理集群、服务器群或者合作执行任务或执行应用或服务的其它计算机组织。服务器630可包括被组织为模块、方法、对象、函数、例程或叫用的一组或多组指令。所述指令可被组织为一个或多个计算机程序、操作系统服务或包含移动app的应用程序。指令可包括操作系统及/或系统软件;支持多媒体、编程或其它功能的一个或多个库;实施TCP/IP、HTTP或其它通信协议的数据协议指令或堆栈;解释或再现使用HTML、XML、JPEG、MPEG或PNG来编码的文件的文件格式处理指令;为图形用户接口(GUI)、命令行接口或文本用户接口再现或解释命令的用户接口指令;应用软件,诸如办公套件、互联网接入应用、设计及制造应用、图形应用、音频应用、软件工程应用、教育应用、游戏或各种应用。服务器830可包括web应用服务器,所述web应用服务器托管呈现层、应用层及数据存储层,诸如使用结构化查询语言(SQL)或NoSQL的关系数据库系统、对象存储体、图形数据库、平面文件系统或其它数据存储装置。
计算装置800可通过网络、网络链路820及通信接口818发送消息并接收数据及指令,包含程序代码。在互联网示例中,服务器830可通过互联网828、ISP 826、本地网络822及通信接口818传输应用程序的请求代码。所接收代码可在其被接收时由处理器804执行,或者存储在存储装置810或其它非易失性存储装置中以供稍后执行。
基本软件系统
图9是可用于控制图8的计算装置800的操作的示例性基本软件系统900的框图。软件系统900及包含其连接、关系及功能的其组件仅意味着是示例,且并不意味着限制所述技术的实施方式。适合于实施所述技术的其它软件系统可具有不同组件,包含具有不同连接、关系及功能的组件。
提供软件系统900用于引导计算机系统800的操作。可存储在系统存储器(RAM)806中及存储在固定存储装置(例如,硬盘或快闪存储器)810上的软件系统900包含内核或操作系统(OS)910。
OS 910管理计算机操作的低级方面,包含管理表示为902-1、902-2、902-3、…、902-N的过程的执行、存储器分配、文件输入及输出(I/O)以及装置I/O。一个或多个应用程序可被“加载”(例如,从固定存储装置810传送到存储器806)以由系统900作为一个或多个过程来执行。旨在供用于计算装置800上的应用或其它软件也可被存储为一组可下载计算机可执行指令,例如,用于从互联网位置(例如,Web服务器、app商店或其它在线服务)下载及安装。
应用程序指令的执行可以正被执行并由程序代码及其当前活动组成的计算机程序的实例的形式实施过程(例如,902-2)。取决于操作系统(OS),过程(例如,902-3)可由并发地执行指令的多个执行线程组成。在此上下文中,计算机程序是指令的被动集合,而过程(例如,902-1)可以是那些指令的实际执行。数个过程(例如,902-1及902-2)可与同一程序相关联;例如,开始运行同一程序的数个实例通常意味着正在执行不止一个过程,或者最初作为单个过程启动的程序可能随后产生(例如,衍生)额外过程。
OS 910可实施多任务处理,以允许过程902-1、902-2、902-3、…、902-N共享处理器804。虽然每一处理器804或处理器的核心每次执行单个任务,但计算装置800可经编程以实施多任务处理,以允许每一处理器在正在执行的任务之间切换,而不必等待每一任务完成。当任务执行输入/输出操作时,当任务指示其可进行切换时,或者其在硬件中断时,可执行切换。通过快速执行上下文切换以提供多个过程同时并行执行的表观,可实施时间共享以允许交互式用户应用的快速响应。为了安全性及可靠性,OS 910可防止独立过程之间的直接通信,从而提供经严格调解及控制的过程间通信功能。
在一些实例中,过程902-1、902-2、902-3、…、902-N以及其实施的应用程序可在应用容器940内执行。应用容器通常是OS 910的操作模式,其中OS 910允许存在多个经隔离用户空间实例在OS 910上运行。应用容器940是一个此种实例的示例。另一选择是,实例本身有时也被称为区带、虚拟私有服务器、分区、虚拟环境、虚拟内核或监狱。应用容器提供一种机制,由此可在实例当中分配有限硬件计算资源,诸如CPU时间及存储介质空间。
软件系统900包含图形用户接口(GUI)915,用于以图形方式(例如,“点击”或“触摸手势”)接收用户命令及数据。这些输入又可由系统900根据来自操作系统910或过程902-1、902-2、902-3、…、902-N的指令来执行动作。GUI 915还用于显示来自OS 910及过程902-1、902-2、902-3、…、902-N 902的操作结果,由此用户可提供额外输入或终止会话(例如,注销)。
OS 910可直接在计算装置800的裸硬件920(例如,处理器804)上执行。另一选择是,管理程序或虚拟机监控器(VMM)930可插置在裸硬件920与OS 910之间。在此配置中,VMM930充当OS 910与计算装置800的裸硬件920之间的软件“缓冲”或虚拟化层。
VMM 930实例化并运行一个或多个虚拟机实例(“客户机器”)。每一客户机器包括诸如OS 910的“客户端”操作系统,以及经设计以在客户端操作系统上执行的一个或多个应用,诸如应用902。VMM 930向客户端操作系统提供虚拟操作平台,并管理客户端操作系统的执行。
在一些实例中,VMM 930可允许客户端操作系统运行,就好像其直接在计算装置800的裸硬件920上运行一样。在这些实例,经配置以直接在裸硬件920上执行的同一版本的客户端操作系统也可在VMM 930上执行,而无需进行修改或重新配置。换句话说,在一些实例中,VMM 930可将完全硬件及CPU虚拟化提供给客户端操作系统。
在其它实例中,客户端操作系统可经专门设计或配置以在VMM 930上执行。在这些实例中,客户端操作系统“意识到”其在虚拟机监控器上执行。换句话说,在一些实例中,VMM930可向客户端操作系统提供半虚拟化。
云计算
所述技术可在“云计算”环境中实施。术语“云计算”在本文中一般用于描述一种计算模型,所述计算模型使得能够对诸如计算机网络、服务器、软件应用及服务等计算资源的共享池进行按需访问,并且允许以最少管理努力或服务提供商交互来快速供应及释放资源。
云计算环境(有时称为云环境或云)可通过各种不同方式来实施,以最大限度地满足不同要求。例如,在公共云环境中,底层计算基础设施由使其云服务可供其它组织或公众使用的组织拥有。相比来说,私有云环境一般仅供单个组织使用或在单个组织内部使用。社区云旨在由社区内的数个组织共享;而混合云包括两种或更多种类型的云(例如私有、社区或公共),其通过数据及应用可移植性绑定在一起。
一般来说,云计算模型使得先前可能由组织自身信息技术部门提供的那些职责中的一些能够在云环境内作为服务层交付,以供消费者使用(根据云的公共/私有性质,在组织内或在组织外部)。根据特定实施方式,由每一云服务层提供或在每一云服务层内的部件或特征的精确定义可能会有所不同,但通用示例包含:软件即服务(SaaS),其中消费者使用在云基础设施上运行的软件应用,而SaaS提供商管理或控制底层云基础设施及应用。平台即服务(PaaS),其中消费者可使用由PaaS提供商支持的软件编程语言及开发工具来开发、部署及控制其自身应用,而PaaS提供商管理或控制云环境的其它方面(例如,运行时执行环境下的所有内容)。基础设施即服务(IaaS),其中消费者可部署及运行任意软件应用,及/或对处理、存储装置、网络及其它基础计算资源进行配置,而IaaS提供商管理或控制底层物理云基础设施(例如,操作系统层下的所有内容)。数据库即服务(DBaaS),其中消费者使用在云基础设施上运行的数据库服务器或数据库管理系统,而DbaaS提供商管理或控制底层云基础设施、应用及服务器,包含一个或多个数据库服务器。
本公开的其它方面
除非上下文另有明确指示,否则术语“或”在前述说明书及所附权利要求书中以其包含性意义(而非其排他性意义)使用,因此当用于例如连接一列表的元件时,术语“或”意指列表中的一个、一些或所有元件。
除非上下文另有明确指示,否则术语“包括”、“包含”、“具有”、“基于”、“囊括”等等以开放式方式在前述说明书及所附权利要求书中使用,并且不排除额外元件、特征、动作或操作。
除非上下文另有明确指示,否则诸如短语“X、Y及Z中的至少一者”的连接性语言应理解为传达物品、项等可以是X、Y或Z,或者其组合。因此,此种连接性语言并不旨在默认地要求X中的至少一者、Y中的至少一者及Z中的至少一者各自存在。
除非上下文另有明确指示,否则如在前述具体实施方式及所附权利要求书中所使用,单数形式“a”、“an”及“该”也旨在包含复数形式。
除非上下文另有明确指示,否则在前述具体实施方式及所附权利要求书中,尽管术语第一、第二等在一些实例中在本文中用于描述各种元件,但这些元件不应受到这些术语的限制。这些术语仅用于将一个元件与另一元件区分开。例如,第一计算装置可被称为第二计算装置,并且类似地,第二计算装置可被称为第一计算装置。第一计算装置及第二计算装置都是计算装置,但其并非同一计算装置。
在前述说明书中,已参考众多具体细节描述这些技术,所述具体细节可根据实施方式的不同而变化。因此,说明书及图式被认为是说明性意义而不是限制性意义。

Claims (17)

1.一种由至少一个计算装置实施的方法,其包括:
检测库的编程语言源代码中的具体数据类型定义;
确定所述具体数据类型定义是否允许运行时潜在引用循环;以及
基于确定所述具体数据类型定义允许运行时引用循环,暂停所述编程语言源代码的编译或将与所检测的潜在引用循环有关的警示输出到用户接口、文件、数据库或集成式开发环境。
2.根据权利要求1所述的方法,其中确定所述具体数据类型定义是否允许运行时潜在引用循环是基于:
确定所述编程语言源代码中的所述具体数据类型定义的性质定义是否是只读的。
3.根据权利要求2所述的方法,其中确定所述编程语言源代码中的所述具体数据类型定义的所述性质定义是否是只读的是基于:
识别所述性质定义中指示所述性质定义为只读的关键字;或
基于以下内容来推断所述性质定义是只读的:基于对所述编程语言源代码的分析来确定在向所述性质指派初始值之后能够设定所述性质的值的所述编程语言源代码中任一者都不这样做。
4.根据权利要求1所述的方法,其中确定所述具体数据类型定义是否允许运行时潜在引用循环是基于:
确定所述编程语言源代码中的所述具体数据类型定义的性质定义是否是早期的。
5.根据权利要求4所述的方法,其中确定所述编程语言源代码中的所述具体数据类型的所述性质定义是否是早期的是基于:
识别所述性质定义中指示所述性质定义为早期的关键字;或
基于以下内容来推断所述具体数据类型定义是早期的:基于对所述编程语言源代码的分析来确定在对含有所述性质的数据对象的任何引用被用作值之前向所述性质指派初始值而不是所述数据对象仅仅被用于将所述数据对象的性质初始化。
6.根据权利要求1所述的方法,其中确定所述具体数据类型定义是否允许运行时潜在引用循环是基于:
确定所述编程语言源代码中的所述具体数据类型定义是否是封闭的。
7.根据权利要求6所述的方法,其中确定所述编程语言源代码中的所述具体数据类型定义是否是封闭的是基于:
识别所述具体数据类型定义中指示所述具体数据类型定义为封闭的关键字;或
基于以下内容来推断所述具体数据类型定义是封闭的:基于对所述编程语言源代码的静态分析来确定不存在所述具体数据类型定义的子数据类型的定义。
8.根据权利要求1所述的方法,其还包括:
基于识别所述具体数据类型定义中指示所述具体数据类型定义为具体的关键字来确定所述具体数据类型定义是具体的。
9.根据权利要求1所述的方法,其还包括:
基于以下内容来确定所述具体数据类型定义是具体的:基于将所述具体数据类型的实例化识别为所述编程语言源代码中的对象来推断所述具体数据类型定义是具体的。
10.根据权利要求1所述的方法,其中确定所述具体数据类型定义是否允许运行时潜在引用循环是基于:
构造所述具体数据类型定义的数据类型定义图形,所述数据类型定义图形包括表示数据类型的节点以及对应于关于泛型类型参数的最坏情形假设的一个或多个节点。
11.根据权利要求10所述的方法,其中所述最坏情形假设考虑了泛型类型参数或数据类型定义的界限。
12.根据权利要求10所述的方法,其中所述数据类型定义图形包括与一种数据类型可引用另一数据类型的方式对应的一个或多个边。
13.根据权利要求10所述的方法,其中确定所述具体数据类型定义是否允许运行时潜在引用循环是基于:
检测所述数据类型定义图形中具有特定种类的边的循环。
14.根据权利要求10所述的方法,其中:
所述警示包括所述潜在引用循环的人类可读描述;
所述人类可读描述(a)是从与所述数据类型定义图形的节点或边相关联的元数据派生的或者(b)包括关于如何避免所述潜在引用循环的建议。
15.根据权利要求14所述的方法,其中将所述警示输出到的集成式开发环境使用所述警示来基于由用户选择的建议自动改变编程语言源。
16.根据权利要求1所述的方法,其还包括:
基于(a)与所述具体数据类型定义相关联的提示、注解或元数据或者(b)确定所述具体数据类型定义是在所述编程语言源代码的特定所指定部分内定义的来确定所述潜在引用循环已被认为是安全的。
17.根据权利要求1所述的方法,其还包括:
在分布式对象系统中,使用进行引用计数来将作为所述具体数据类型的实例的对象解除分配,其中经解除分配的对象分布在多个计算过程之上。
CN202180094311.7A 2020-12-22 2021-12-21 防止最小运行时上的垃圾对象积累 Pending CN117355818A (zh)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US17/131,583 US10963228B1 (en) 2020-12-22 2020-12-22 Preventing garbage object accumulation on minimal runtimes
US17/131,583 2020-12-22
PCT/US2021/064529 WO2022140332A2 (en) 2020-12-22 2021-12-21 Preventing garbage object accumulation on minimal runtimes

Publications (1)

Publication Number Publication Date
CN117355818A true CN117355818A (zh) 2024-01-05

Family

ID=75164472

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202180094311.7A Pending CN117355818A (zh) 2020-12-22 2021-12-21 防止最小运行时上的垃圾对象积累

Country Status (6)

Country Link
US (3) US10963228B1 (zh)
EP (1) EP4268068A2 (zh)
JP (1) JP7542175B2 (zh)
CN (1) CN117355818A (zh)
CA (1) CA3205948C (zh)
WO (1) WO2022140332A2 (zh)

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US11625226B1 (en) * 2021-10-04 2023-04-11 Salesforce.Com, Inc. Data flow retyping for functional programming languages

Citations (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101169718A (zh) * 2006-10-23 2008-04-30 国际商业机器公司 用于实例化抽象类的系统和方法
US20100174893A1 (en) * 2009-01-05 2010-07-08 International Business Machines Corporation Runtime checking of dynamic subranges
CN102402451A (zh) * 2010-09-28 2012-04-04 微软公司 用户定义类型的编译时边界检查
US20120233592A1 (en) * 2012-05-01 2012-09-13 Concurix Corporation Meta Garbage Collection for Functional Code
CN106133685A (zh) * 2014-03-27 2016-11-16 微软技术许可有限责任公司 对运行时行为的基于分层指令的管理

Family Cites Families (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US6742175B1 (en) * 1998-10-13 2004-05-25 Codagen Technologies Corp. Component-based source code generator
US20100037213A1 (en) * 2008-08-07 2010-02-11 Microsoft Corporation Grammar-based generation of types and extensions
US8776094B2 (en) * 2011-08-11 2014-07-08 Microsoft Corporation Runtime system
JP5667948B2 (ja) 2011-09-06 2015-02-12 株式会社東芝 プログラム検査装置
US9971632B2 (en) * 2014-11-13 2018-05-15 Soundspectrum, Inc. Synchronization and barrier free concurrent garbage collection system

Patent Citations (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101169718A (zh) * 2006-10-23 2008-04-30 国际商业机器公司 用于实例化抽象类的系统和方法
US20100174893A1 (en) * 2009-01-05 2010-07-08 International Business Machines Corporation Runtime checking of dynamic subranges
CN102402451A (zh) * 2010-09-28 2012-04-04 微软公司 用户定义类型的编译时边界检查
US20120233592A1 (en) * 2012-05-01 2012-09-13 Concurix Corporation Meta Garbage Collection for Functional Code
CN106133685A (zh) * 2014-03-27 2016-11-16 微软技术许可有限责任公司 对运行时行为的基于分层指令的管理

Non-Patent Citations (1)

* Cited by examiner, † Cited by third party
Title
MARCOS VIERA 等: "Haskell, do you read me?: constructing and composing efficient top-down parsers at runtime", 《HASKELL \'08: PROCEEDINGS OF THE FIRST ACM SIGPLAN SYMPOSIUM ON HASKELL》, 25 September 2008 (2008-09-25), pages 63 *

Also Published As

Publication number Publication date
WO2022140332A2 (en) 2022-06-30
US20220197612A1 (en) 2022-06-23
US12073198B2 (en) 2024-08-27
JP7542175B2 (ja) 2024-08-30
US11698778B2 (en) 2023-07-11
JP2023551746A (ja) 2023-12-12
CA3205948C (en) 2024-06-18
WO2022140332A3 (en) 2022-08-04
US20240028316A1 (en) 2024-01-25
CA3205948A1 (en) 2022-06-30
EP4268068A2 (en) 2023-11-01
US10963228B1 (en) 2021-03-30

Similar Documents

Publication Publication Date Title
Chandy et al. CC++: A declarative concurrent object-oriented programming notation
US8863082B2 (en) Transformational context-aware data source management
ES2471394T3 (es) Programación y ejecución orientadas por gráficos de productor
CN102866884B (zh) 将本机应用编程接口投射到其他编程语言的方法和设备
US7596782B2 (en) Software build extensibility
US11036482B1 (en) Deriving many idiomatic programming language interfaces
US20210365277A1 (en) Static reconcilliation of application view hierarchies
US20090204944A1 (en) Generic xad processing model
Spoto A java framework for smart contracts
US12073198B2 (en) Preventing garbage object accumulation on minimal runtimes while supporting an implicit deallocation programming experience
Ortin et al. Dynamic adaptation of application aspects
US7526752B1 (en) Introspection support for generic types
Ali Advanced IOS 4 Programming: Developing Mobile Applications for Apple IPhone, IPad, and IPod Touch
Harvey A linguistic approach to concurrent, distributed, and adaptive programming across heterogeneous platforms
US20240143485A1 (en) Presubmit Test Run Minimization Analysis Using Runtime Isolation Guarantees
Marevac et al. Design and Implementation of a Virtual Machine for a Dynamic Object-Oriented Programming Language
He Type-parameterized actors and their supervision
CN113778420B (zh) 桥接模块系统和非模块系统
Ali iPhone SDK 3 Programming
Ali iPhone SDK 3 programming: advanced mobile development for Apple iPhone and iPod touch
Ahmed State Controlled Object Oriented Programming
Tatsubori A Class-Object Model for Program Transformations
Pastorek Deployment of SOFA 2 applications for embedded environment
Chirila et al. Elements of Software Engineering

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination