4个版本

0.2.2 2024年5月10日
0.2.1 2024年4月20日
0.1.1 2024年4月20日
0.1.0 2024年4月20日

#54编程语言

Download history 20/week @ 2024-04-26 152/week @ 2024-05-10 19/week @ 2024-05-17 3/week @ 2024-05-24 1/week @ 2024-06-07

192 每月下载量

MIT 许可证

91KB
2K SLoC

impc

IMP编程语言的编译器。目前,impc run <program> 将解析给定的程序并调用有效的树遍历解释器;在这种情况下,它已经准备好用于执行IMP程序的相对简单任务。开发重点已经转移到实现一个针对LLVM的最小优化后端,这将取代解释器,当功能完全时。

安装和使用

假设您已在系统上安装了Rust工具链(如果没有,请遵循这些说明),那么可以使用 impc 来安装,使用 cargo install

# from crates.io
cargo install impc

# from source
cargo install --git https://github.com/eikopf/impc.git

安装了 impc 后,运行 impc --helpimpc run --help 以获取其使用细节。要运行IMP程序,可以使用 impc run <filename> 命令,如果需要,可以使用 --let 选项显式提供绑定以避免交互式提示阶段。

IMP

从很大程度上说,IMP是一种非常无趣的语言;它的整个语法可以放在一个30行的ANTLR4 .g4 文件中(见下文),其语义非常简单。

在IMP中,

  1. 所有变量总是处于作用域内,并且在执行之前必须具有已绑定值;
  2. 算术表达式使用无符号整数语义进行评估,但减法饱和在0;
  3. 算术表达式始终定义,因此整数溢出是未定义行为;
  4. 由于整数溢出是UB并且整数没有指定的位宽,因此严格正确的实现应该使用任意精度整数,除非它可以证明某些固定宽度的类型不会发生溢出;
  5. 布尔表达式具有普通布尔语义;
  6. 布尔和算术表达式不定义评估顺序,因为它们不能产生副作用;
  7. 命令按顺序执行,只有赋值命令可以产生副作用(即值绑定);
  8. whileif 命令的行为符合预期的语义。

这些属性允许IMP具有一个有趣的特性:它可以被积极优化。一般来说,只要保持赋值命令的顺序,命令可以任意重新排序,并且有时可以证明赋值命令的任意重新排序都是有效的(即,如果它们是互斥的)。在更复杂的情况下,这些属性可以用来展开、内联或几乎完全删除 whileif 命令。

grammar IMP;

aexp : INT                                        #Atom
     | VAR                                        #Variable
     | '(' inner=aexp ')'                         #Brackets
     | left=aexp '*' right=aexp                   #Mult
     | left=aexp '+' right=aexp                   #Add
     | left=aexp '-' right=aexp                   #Sub
     ;

bexp : 'true'                                     #True
     | 'false'                                    #False
     | left=aexp '=' right=aexp                   #Equal
     | left=aexp '<' right=aexp                   #Smaller
     | left=aexp '>' right=aexp                   #Greater
     | left=aexp '<>' right=aexp                  #Inequality
     | 'not' inner=bexp                           #Not
     | '(' left=bexp 'and' right=bexp ')'         #And
     | '(' left=bexp 'or' right=bexp ')'          #Or
     ;

cmd  : 'skip'                                                               #Skip
     | variable=VAR ':=' expression=aexp                                    #Assignment
     | first=cmd ';' second=cmd                                             #Sequence
     | 'if' condition=bexp 'then' truecase=cmd 'else' falsecase=cmd 'fi'    #If
     | 'while' condition=bexp 'do' body=cmd 'od'                            #While
     ;
     
VAR  : [a-zA-Z][a-zA-Z0-9_]* ;
INT  : [0-9]+ ;
WS   : [ \r\n\t] -> skip ;

依赖关系

~6-14MB
~188K SLoC