如何在.travis.yml中指定:language:none?我没有指定语言,默认情况下获取Ruby.我没有Ruby.我正在使用C,C++,Ocaml,Python和Felix.构建脚本只是"make".
我在编组数据结构时失败(错误抽象类型(自定义)).有一种已知的抽象类型,即Big_int.然而那个法警很好.应用程序中没有自定义C代码.除了Nums之外,还使用了Unix库(但我不相信有任何类型的活动对象).我们是关闭闭锁的元帅.
正在使用两个(仅)第三方库:OCS Scheme(Scheme解释器,纯Ocaml)和Dypgen(可扩展GLR解析器,也是纯Ocaml).问题在于Dypgen的一个新功能,它保存了一个动态扩展的解析器.
Ocaml错误消息旁边是无用的(它不能识别哪个抽象类型与Custom标签是罪魁祸首).
我们怀疑Lexbuf是罪魁祸首,因为它包含一个Ocaml通道上的封闭,并且不能被元帅,但似乎这不是问题所在.所以我的问题是:
哪个标准库组件不能马歇尔?
我很好奇是否有任何(仅限一阶多态)优化折叠.
对于地图,有砍伐森林:map g (map f ls) => map (g . f) ls
和rev (map f ls) => rev_map f ls
(在Ocaml中更快).
但折叠是如此强大,它似乎无视任何优化.
有没有人知道任何论文讨论内联算法?并且密切相关,父子图与调用图的关系.
背景:我编写了一个编译器,Ocaml
其中积极地内联函数,主要是由于这个和其他一些优化,它为我的编程语言生成比许多其他情况(包括偶数C
)更快的代码.
问题#1:算法在递归时遇到问题.为此,我的规则只是将子项内联到父项中,以防止无限递归,但这会阻止兄弟函数一次性内联.
问题2:我不知道优化内联操作的简单方法.我的算法对于函数体的可变表示是势在必行的,因为它甚至不可能实现有效的函数内联算法.如果调用图是一棵树,很明显自下而上的内联是最佳的.
技术信息:内联包含许多内联步骤.问题是步骤的顺序.
每个步骤的工作原理如下:
克隆操作使得内联递归函数变得非常困难.保持已经在进行中的列表并且只是检查我们是否已经处理此调用的常用技巧不能以天真的形式工作,因为递归调用现在被转移到调整后的代码中.函数,递归目标可能已更改为克隆的子项.但是,该子进程在调用父进程时仍在调用调用其子进程的原始父进程,现在不会停止展开递归.如上所述,我通过仅允许对孩子进行递归调用来打破此回归,从而防止内联的兄弟递归.
由于需要garbage collect
使用未使用的功能,因此内联成本更加复杂.由于内联可能具有指数性,因此这是必不可少的.如果对函数的所有调用都是内联的,那么如果尚未内联函数,我们应该删除该函数,否则我们将浪费时间内联到一个不再使用的函数中.实际上跟踪谁调用极其困难的东西,因为在内联时我们不使用实际的函数表示,而是"解开"的表示:例如,正在按顺序处理指令列表并构建新列表,并且在任何一个时间点可能没有连贯的指令列表.
在他的ML编译器中,Steven Weeks选择使用多次重复应用的小优化,因为这使得优化易于编写且易于控制,但不幸的是,与递归算法相比,这错过了许多优化机会.
问题3:内联函数调用何时安全?
一般来说解释这个问题:在一个懒惰的函数式语言中,参数包含在闭包中,然后我们可以内联一个应用程序; 这是Haskell的标准模型.然而,它也解释了为什么Haskell
这么慢.如果参数已知,则不需要闭包,那么参数可以直接替换其出现的参数(这是正常的顺序beta-reduction
).
但是,如果已知参数评估不是非终止的,则可以使用急切评估:为参数分配表达式的值一次,然后重复使用.这两种技术的混合使用闭包但将结果缓存在闭包对象中.尽管如此,GHC还没有成功地生成非常高效的代码:显然非常困难,特别是如果你有单独的编译.
在菲利克斯,我采取了相反的方法.通过证明优化保留语义,而不是要求正确性并逐步提高效率,我要求优化定义语义.这保证了优化器的正确操作,但代价是不确定某些代码将如何表现.我们的想法是为程序员提供一些方法,以便在默认优化策略过于激进时强制优化器符合预期的语义.
例如,默认参数传递模式允许编译器选择是将参数包装在闭包中,用参数替换参数,还是将参数赋值给参数.如果程序员想要强制关闭,他们就可以传递一个闭包.如果程序员想要强制进行评估,他们会标记参数var
.
这里的复杂性比函数式编程语言要大得多:Felix是一个带变量和指针的过程语言.它还有Haskell风格的类型.这使得内联例程极其复杂,例如,类型类实例尽可能替换抽象函数(由于在调用多态函数时类型特化,在内联时可能会找到一个实例,所以现在我们有了一个新函数可以内联).
为了清楚起见,我必须添加一些注释.
内联和其他一些优化,例如用户定义的术语缩减,类型类实例化,线性数据流检查变量消除,尾部rec优化,都是在给定函数上同时完成的.
排序问题不是应用不同优化的顺序,问题是订购功能.
我使用脑死算法来检测递归:我建立了每个函数直接使用的所有内容的列表,找到闭包,然后检查函数是否在结果中.请注意,在优化过程中,使用集会多次构建,这是一个严重的瓶颈.
函数是否递归可能会发生变化.尾部优化后,递归函数可能变为非递归.但是有一个更难的情况:实例化类型类"虚拟"函数可以使看似非递归的递归.
至于兄弟调用,问题是给定f和g,其中f调用g和g调用f我实际上想要将f内联到g中,并将g内联到f ..一次.我的无限回归停止规则是只允许将f内联到g如果它们是相互递归的,如果f是g的子,则不包括内联兄弟.
基本上我想"尽可能"地"平掉"所有代码.
algorithm ocaml compiler-theory compiler-optimization graph-algorithm
我不确定我是否知道如何提出这个问题.在实现编译器时,我想允许客户端指定,例如,在元组上折叠.我提供了一种方法来curry和uncurry一个函数,但这只是因为我在Ocaml中编写了一个二元运算符并将其折叠在术语和类型表示上.用户无法编写此功能.
在宏处理器中,用户可以编写此函数,因为元组是列表.
对于curried函数,用户可以轻松编写变换器,因为该术语在目标语言和术语的Ocaml表示以及键入时都是二进制的.
但他们不能为元组做这件事.这是另一个例子:用户可以轻松定义串行功能组合运算符.但用户无法定义并行组合:二进制版本:
f1: D1 -> C1, f2: D2-> C2 --> f1 * f2: D1 * D2 -> C1 * C2
Run Code Online (Sandbox Code Playgroud)
很容易写,但不能扩展到3个术语:这里折叠会计算
f1 * (f2 * f3)
Run Code Online (Sandbox Code Playgroud)
代替
f1 * f2 * f3
Run Code Online (Sandbox Code Playgroud)
[同构但不相等]
这个问题的概括是"我如何实现一种多语言编程语言",这里有点太多了.我试图做的是提供内置变压器:
咖喱:T1*T2*T3 ...... - > T1 - > T2 - > ......不发生:T1 - > T2 - > .. T1*T2*T3
那么用户可以用二元运算符进行折叠:
uncurry (fold user_op (uncurry term))
Run Code Online (Sandbox Code Playgroud)
但这既不够通用,也不是很好.. :)
我想Haskell的一个等价问题是:由于Haskell没有n-ary产品,n-ary元组构造函数在库中用n个函数模拟,其中每个函数必须手工写出.这显然很糟糕.这将如何解决?
[我的意思是,编写一个Python脚本来生成那些n个函数达到某个极限n是微不足道的,那么为什么在语言中以一种好的方式这么做呢?]
我想详细解释这个问题.在许多具有强类型系统的语言中(如Felix,Ocaml,Haskell),您可以通过组合类型构造函数来定义多态列表.这是Felix的定义:
typedef list[T] = 1 + T * list[T];
typedef list[T] = (1 + T * self) as self;
Run Code Online (Sandbox Code Playgroud)
在Ocaml:
type 'a list = Empty | Cons ('a, 'a list)
Run Code Online (Sandbox Code Playgroud)
在C中,这是递归的,但既不是多态的也不是组合的:
struct int_list { int elt; struct int_list *next; };
Run Code Online (Sandbox Code Playgroud)
在C++中,如果C++支持类型递归,它将像这样完成:
struct unit {};
template<typename T>
using list<T> = variant< unit, tuple<T, list<T>> >;
Run Code Online (Sandbox Code Playgroud)
给出了元组(又名对)和变体(但不是Boost中使用的破坏的)的合适定义.或者:
using list<T> = variant< unit, tuple<T, &list<T>> >;
Run Code Online (Sandbox Code Playgroud)
鉴于变体的定义略有不同,可能是可以接受的.甚至不可能在C++ <C++ 11中编写它,因为如果没有模板typedef,就没有办法获得多态性,并且没有typedef的合理语法,就无法在范围内获取目标类型.上面的using语法解决了这两个问题,但这并不意味着允许递归.
特别请注意,允许递归对ABI有重大影响,即名称修改(除非名称修改方案允许表示修复点,否则无法完成).
我的问题:需要在C++ 11中工作吗?[假设扩展不会导致无限大的结构]
编辑:为了清楚起见,要求是一般结构类型.例如,模板提供了精确的信息
pair<int, double>
pair<int, pair <long, double> >
Run Code Online (Sandbox Code Playgroud)
是匿名的(结构上)类型,并且对显然是多态的.但是,C++ <C++ 11中的递归无法说明,即使使用指针也是如此.在C++ …
运行最新的Cygwin64,Window 10,startxwin
给出:
winClipboardProc - XOpenDisplay () returned and successfully opened the display.
winMultiWindowXMsgProcErrorHandler - ERROR: BadMatch (invalid parameter attributes)
Run Code Online (Sandbox Code Playgroud)
然后挂起 有线索吗?
C ++模块TS为消除预处理器,缩短编译时间,并为至少非模板代码至少支持C ++中更健壮,模块化的代码开发提供了绝佳的工具。
底层机制可控制普通程序中符号的导入和导出。
但是,开发用于两种动态加载的库存在一个主要问题:启动时加载和运行时加载。此问题涉及从库中导出符号,通常会在可见性方面进行讨论。
通常,并非所有用于构建动态链接库的翻译单元的外部符号都应对用户可见。此外,在运行时加载时,尤其是在使用插件概念加载时,必须从许多同时加载的库中导出同一符号。
在Windows上使用语言扩展
__declspec(dllexport)
__declspec(dllimport)
Run Code Online (Sandbox Code Playgroud)
附加在源代码中作为符号的属性,最近在unix平台上的gcc和clang系统上,
__attribute__((visibility("default")))
__attribute__((visibility("hidden")))
Run Code Online (Sandbox Code Playgroud)
旨在支持打算由图书馆公开的符号的提供和使用。使用它们是复杂且混乱的:在Windows上,在编译库时必须使用宏来导出符号,而在使用它们时则要导入它们。在unix平台上,必须将可见性设置为默认设置,以同时导出和导入符号,由编译器根据是否找到定义来决定其自身:必须使用以下命令调用编译器:
-fvisibility=hidden
Run Code Online (Sandbox Code Playgroud)
开关。静态链接不需要export / import属性,可能应该将其宏化为空字符串。编写代码并摆弄构建系统,以使所有这些工作正常进行,尤其是考虑到#include必须在库翻译单元的编译过程中设置正确的符号可见性,这非常困难,存储库中所需的文件结构混乱,源代码杂乱无章与宏,总的来说,整个事情都是一场灾难。几乎所有开放源代码存储库都无法正确导出符号以进行动态链接,并且大多数程序员都不知道动态库代码结构(使用两级名称空间)与静态链接完全不同。
可以在此处看到如何执行此操作的示例(希望正确):
https://github.com/calccrypto/uint256_t
该存储库曾经有2个标头和2个实现文件,内置库的用户将看到2个标头。现在有7个头文件和2个实现文件,内置库的用户将看到5个头文件(其中3个扩展名include
表示不直接包含这些文件)。
因此,在经过漫长的解释之后,问题是:最终的C ++模块规范是否有助于解决动态链接符号的导入和导出问题?我们可以期望能够开发共享库而不会用供应商特定的扩展名和宏来污染我们的代码吗?
有谁知道GC算法利用类型信息来允许增量收集,优化收集,并行收集或其他一些不错的功能?
通过类型信息,我的意思是真正的语义.让我举一个例子:假设我们有一个OO样式类,其中包含维护隐藏表示的列表的方法.当对象变得无法访问时,收集器可以在列表中运行,删除所有节点.由于封装,它知道它们现在都无法到达.它还知道不需要对指针进行常规的节点扫描,因为它知道所有节点都是相同的类型.
显然,这是一个特殊情况,可以使用C++中的析构函数轻松处理.真正的问题是,是否有办法分析程序中使用的类型,并指示收集器使用结果信息来获益.我想你会称这是一个类型导向的垃圾收集器.
有一个相关的问题,但这个有点不同,我对相关问题的任何答案都不满意:)
我将通过断言不可能为C++提供可选的透明垃圾收集器并希望有人证明我错了,从而对这个问题提出质疑.是的,Stroustrup尝试了这一点并且一再失败,不是因为技术问题,而是因为一致性问题.性能不是问题.
C++永远不会有这样一个收集器的原因是,在没有收集器的情况下运行的程序是可选的,必须手动实现所有必需的内存管理.添加收集器可能会带来一些性能优势,但不清楚它们是否值得(是的,收集器可以更快).
你无法获得的是自动内存管理,这是渴望收集器的主要原因.您可以通过强制收集获得此功能(如果您选择进行正确的手动管理,则无需牺牲RAII或其他内容).具有可选手动内存管理功能的强制收集器是可行的.
不幸的是,获得强制收集器的唯一方法是创建与不使用收集器的早期版本的C++不兼容:换句话说,如果我们想要自动透明内存管理,我们必须定义一种新语言.
所以我的论点是:C++永远不会有垃圾收集,因为它被锁定在需要向上兼容的历史开发中:强制收集和可选的手动内存管理是可行的,但透明的可选垃圾收集不是.
通过展示一个可选的透明垃圾收集模型证明我错了!
编辑:
噢..我想我有答案.有人可以引用标准,它需要程序删除堆分配的对象吗?
因为:该子句(如果存在)是唯一阻止可选透明垃圾收集的子句.甚至可能有足够的时间从C++ 1x中删除该子句.
如果没有这样的子句,程序可能会泄漏内存而不会出现未定义的行为:内存不足时的行为与通常情况相同.因此,对垃圾收集器执行操作将不会对指定的语义执行任何操作:它们是否定义良好,与是否使用收集器无关.
ocaml ×5
c++ ×4
algorithm ×2
c++-modules ×1
c++11 ×1
cygwin ×1
fold ×1
marshalling ×1
performance ×1
string ×1
travis-ci ×1
type-theory ×1
types ×1
vector ×1
windows-10 ×1
xserver ×1