- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试用 Haskell 编写一个程序,以对用命令式编程语言编写的类型检查程序进行类型检查。
这里是抽象语法:
type Name = String
-- 程序是一系列(列表)变量声明和一系列(列表)语句。
type Prog = ([TypeEnv],[Stmt])
-- 一个变量声明是一个类型和一个变量名
type TypeEnv = (Type,Name)
-- 类型是“int”或“bool”,或“int[]..[]”或“bool[]..[]”
data Type = BaseType BT | ArrayType BT Int deriving Show
data BT = TyInt | TyBool deriving Show
-- 声明是...
data Stmt =
Assign Name Exp -- ...assignment (<name> := <exp>;)
| If Exp [Stmt] [Stmt] -- ...if-then-else (if <bexp> { <stmt>* } else { <stmt>* })
| While Exp [Stmt] -- ...a while-loop (while <bexp> { <stmt>*> })
| Let Name Exp [Stmt] -- ...let bindings (let <name>=<exp> in { <stmt> *})
| LetArray Name [Exp] Exp [Stmt] -- ...let-array binding (letarray <name> [ <exp> ] .. [ <exp> ] := <exp> in { <stmt>* })
| Case Exp [(Int,[Stmt])] -- ...a case statements
| For Name Exp Exp [Stmt] -- ...a for-loop
| ArrayAssign Name [Exp] Exp -- ...or array assignment (<name> [ <exp> ] .. [ <exp> ] := <exp>;)
deriving Show
-- 表达式是...
data Exp =
Add Exp Exp -- ...addition (<exp> + <exp>)
| Sub Exp Exp -- ...subtract (<exp> - <exp>)
| Mul Exp Exp -- ...multiplication (<exp> * <exp>)
| Neg Exp -- ...negation (-<exp>)
| Var Name -- ...a variable (<name>)
| LitInt Int -- ...an integer literal (e.g. 3, 0, 42, 1999)
| VarArray Name [Exp] -- ...or an array lookup (<name> [ <exp> ])
| IsEq Exp Exp -- ...test for equality (<exp> == <exp>)
| IsNEq Exp Exp -- ...test for inequality (<exp> != <exp>)
| IsGT Exp Exp -- ...test for greater-than (<exp> > <exp>)
| IsLT Exp Exp -- ...test for less-than (<exp> < <exp>)
| IsGTE Exp Exp -- ...test for greater-or-equal (<exp> >= <exp>)
| IsLTE Exp Exp -- ...test for less-or-equal (<exp> <= <exp>)
| And Exp Exp -- ...boolean and (<bexp> && <bexp>)
| Or Exp Exp -- ...boolean or (<bexp> || <bexp>)
| Not Exp -- ...boolean negation (!<bexp>)
| LitBool Bool -- ... or a boolean literal (true or false)
deriving Show
我不需要任何人来完全回答我的问题,但我想提供我目前所知道的,如果有人能指出我正确的方向或者让我知道我是否做错了,那将很有帮助。
对程序进行类型检查的函数从typecheck开始。 typecheck 使用 typecheckstmt 对第一条语句进行类型检查,使用 typecheckstmtlist 对程序的其余部分进行类型检查。然后,这些函数使用 typecheckexp 对任何表达式进行类型检查。显然,我有一个非常基本的实现框架。我只想知道我的方向是否正确,以及是否有人有任何指示。
typecheck :: Prog -> Bool
typecheck _ = True
typecheck (types, x: xs) = (typecheckstmt types x) && (typecheckstmtlist types xs)
typecheckstmt :: [TypeEnv] -> Stmt -> Bool
typecheckstmt _ _ = True
typecheckstmt types (Assign x e) = if checkequaltypes x e
then True && typecheckexp types e
else False
typecheckstmt types (If e stmtlst1 stmtlst2) = typecheckexp types e
&& typecheckstmtlist types stmtlst1
&& typecheckstmtlist types stmtlst2
typecheckstmt types (While e stmtlst) = typecheckexp types e
&& typecheckstmtlist types stmtlst
typecheckstmt types (Let x e stmtlst) = if checkequaltype types x e
then True && typecheckexp types e
&& typecheckstmtlist types stmtlst
else False
typecheckstmt types (LetArray x es e2 stmtlst) =
typecheckstmt types (Case e cases) =
typecheckstmt types (For x e1 e2 stmtlst) = if checkequaltype types x e1
&& checkequaltype types x e2
then True && typecheckstmtlist stmtlst
else False
typecheckstmt types (ArrayAssign x es e2) =
typecheckstmtlist :: [TypeEnv] -> [Stmt] -> Bool
typecheckstmtlist _ _ = True
typecheckstmtlist types [x] = typecheckstmt types x
typecheckstmtlist types x:xs = typecheckstmt types x && typecheckstmtlist types xs
typecheckexp :: [TypeEnv] -> Exp -> Bool
typecheckexp types (Add e1 e2) =
typecheckexp types (Sub e1 e2) =
typecheckexp types (Mul e1 e2) =
typecheckexp types (Neg e1) =
typecheckexp types (Var x) =
typecheckexp types (LitInt i) =
typecheckexp types (VarArray x explist) =
typecheckexp types (IsEq e1 e2) =
typecheckexp types (IsNEq e1 e2) =
typecheckexp types (IsGT e1 e2) =
typecheckexp types (IsLT e1 e2) =
typecheckexp types (IsGTE e1 e2) =
typecheckexp types (IsLTE e1 e2) =
typecheckexp types (And e1 e2) =
typecheckexp types (Or e1 e2) =
typecheckexp types (Not e) =
typecheckexp types (LitBool Bool) =
typecheckexplist :: [TypeEnv] -> [Exp] -> Bool
typecheckexplist _ _ = True
typecheckexplist types [x] = typecheckexp types x
typecheckexplist types x:xs = typecheckexp types x && typecheckexplist types xs
checkequaltype :: [TypeEnv] -> Name -> Exp -> Bool
checkequaltype types x e = getTypeOfVar types x && getTypeOfExp types e
getTypeOfVar :: [TypeEnv] -> Name -> Type
getTypeOfExp :: [TypeEnv] -> Exp -> Type
我也不清楚到底需要检查什么。显然,如果您正在分配和比较变量/表达式,您希望它们是同一类型。
如有任何帮助,我们将不胜感激。
最佳答案
由于没有具体问题,我将只针对该问题提供一些一般性建议。
看来您的方向是正确的。您的方法是正确的,您需要遍历语法树并检查每个子表达式,如果类型不匹配则失败。
typecheckexp :: [TypeEnv] -> Exp -> Bool
typecheckexp types (Add e1 e2) =
case (te1, te2) of
(Just TyInt, Just TyInt) -> True
_ -> False
where
te1 = getTypeOfExp e1
te2 = getTypeOfExp e2
在顶层,您将对所有表达式应用表达式级别检查器,然后将和
所有结果放在一起,以确定您的程序是否作为一个整体进行类型检查。
typecheckexplist :: [TypeEnv] -> [Exp] -> Bool
typecheckexplist env stmts = and (map (typecheckexp env) stmts)
如果你的类型都是预先声明的,并且 TypeEnv 没有因为遍历 AST 而改变,那么这种方法将起作用。如果您在遍历树时构建定义,那么请考虑将类型检查器包装在 State monad 中。 .
Obviously if you are assigning and comparing variables/expressions,
根据您的前端语言,您需要决定是为变量添加显式类型声明(即 int a
),还是尝试从程序的上下文中推断它们,这是一个称为类型推断的单独任务。如果您有来自用户的明确声明,那么您可以简单地根据变量的使用机械地检查给定的类型,并确定它们是否匹配。您的类型都是简单的单体类型,因此这很容易,因为您可以将 (derving Eq
) 附加到您的 Type
并进行类型比较。
要考虑的另一种情况是错误报告,对于给定的 AST,没有附加位置信息,因此如果您遍历树并在中途失败,您将无法告诉用户什么地方失败了。如果您从像 Parsec 这样的解析器解析前端语言,您可以在构建语法树时用信息标记每个数据类型 (Expr Pos
)。
data Expr t = Add t (Expr t) (Expr t) | ...
data Pos = Pos { line :: Integer , col :: Integer }
为了易于使用,您可以查看像 Uniplate 这样的泛型库,它可以让您应用函数并遍历 AST,而无需太多样板文件。提取特定类型的所有节点的人为示例可能是:
{-# LANGUAGE DeriveDataTypeable #-}
module Expr where
import Data.Data
import Data.Typeable
import Data.Generics.Uniplate.Data
data Expr = Val String
| Add Expr Expr
| Sub Expr Expr
| Div Expr Expr
| Mul Expr Expr
| Neg Expr
deriving (Show, Eq, Data, Typeable)
vars :: Expr -> [String]
vars ex = [i | Val i <- universe ex]
test :: [String]
test = vars (Add (Val "a") (Mul (Val "b") (Val "c")))
关于haskell - 编写一个 Haskell 程序,用于对用命令式编程语言编写的程序进行类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20343404/
我只想从客户端向服务器发送数组 adc_array=[w, x, y, z]。下面是客户端代码,而我的服务器是在只接受 json 的 python 中。编译代码时我没有收到任何错误,但收到 2 条警告
我是 lua 和 Node js 的新手,我正在尝试将我正在开发的移动应用程序连接到服务器。问题是它连接到服务器,但我尝试传递的数据丢失或无法到达服务器。对我正在做的事情有什么问题有什么想法吗? th
我在这个页面上工作 http://www.haskell.org/haskellwiki/99_questions/Solutions/4 我理解每个函数的含义,看到一个函数可以像这样以多种方式定义,
我目前正在尝试将数据写入 excel 以生成报告。我可以将数据写入 csv 文件,但它不会按照我想要的顺序出现在 excel 中。我需要数据在每列的最佳和最差适应性下打印,而不是全部打印在平均值下。这
所以,我正在做一个项目,现在我有一个问题,所以我想得到你的帮助:) 首先,我已经知道如何编写和读取 .txt 文件,但我想要的不仅仅是 x.hasNext()。 我想知道如何像 .ini 那样编写、读
我正在尝试编写一个函数,该函数将返回作为输入给出的任何数字的阶乘。现在,我的代码绝对是一团糟。请帮忙。 function factorialize(num) { for (var i=num, i
这个问题已经有答案了: Check variable equality against a list of values (16 个回答) 已关闭 4 年前。 有没有一种简洁或更好的方法来编写这个条件
我对 VR 完全陌生,正在 AFrame 中为一个类(class)项目开发 VR 太空射击游戏,并且想知道 AFrame 中是否有 TDD 的任何文档/标准。有人能指出我正确的方向吗? 最佳答案 几乎
我正在尝试创建一个 for 循环,它将重现以下功能代码块,但以一种更具吸引力的方式。这是与 Soundcould 小部件 API 实现一起使用的 here on stackoverflow $(doc
我有一个非常令人困惑的问题。我正在尝试更改属性文件中的属性,但它只是没有更改... 这是代码: package config; import java.io.FileNotFoundException
我对 VR 完全陌生,正在 AFrame 中为一个类(class)项目开发 VR 太空射击游戏,并且想知道 AFrame 中是否有 TDD 的任何文档/标准。有人能指出我正确的方向吗? 最佳答案 几乎
我正在开发一个用户模式(Ring3)代码级调试器。它还应支持.NET可执行文件的本机(x86)调试。基本上,我需要执行以下操作: 1).NET在隐身模式下加载某些模块,而没有LOAD_DLL_DEBU
我有一个列表,我知道有些项目是不必要打印的,我正在尝试通过 if 语句来做到这一点...但是它变得非常复杂,所以有没有什么方法可以在 if 语句中包含多个索引而无需打印重写整个声明。 看起来像这样的东
我很好奇以不同方式编写 if 语句是否会影响程序的速度和效率。所以,例如写一个这样的: bool isActive = true; bool isResponding = false; if (isA
我在搜索网站的源代码时找到了一种以另一种方式(我认为)编写 if 语句的方法。 代替: if(a)b; 或: a?b:''; 我读了: !a||b; 第三种方式和前两种方式一样吗?如果是,为什么我们要
我的数据采用以下格式(HashMap的列表) {TeamName=India, Name=Sachin, Score=170} {TeamName=India, Name=Sehwag, Score=
我目前正在完成 More JOIN operations sqlzoo 的教程,遇到了下面的代码作为#12 的答案: SELECT yr,COUNT(title) FROM movie JOIN ca
我正试图找到一种更好的方法来编写这段代码: def down_up(array, player) 7.downto(3).each do |row| 8.times do |col
出于某种原因,我的缓冲区中充满了乱码,我不确定为什么。我什至用十六进制编辑器检查了我的文件,以验证我的字符是否以 2 字节的 unicode 格式保存。我不确定出了什么问题。 [打开文件] fseek
阅读编码恐怖片时,我刚刚又遇到了 FizzBuzz。 原帖在这里:Coding Horror: Why Can't Programmers.. Program? 对于那些不知道的人:FizzBu
我是一名优秀的程序员,十分优秀!