4. Consistency Checking
Syntax definition
★ what are well-formed sentences?
Static analysis
★ not all ‘well-formedness’ properties are context-free
★ consistency of compositions
★ consistency of expressions wrt declarations
Error reporting
★ indicate errors in editor
★ use sensible error message
5.
6.
7. Consistency Checking: Ingredients
Editor Interface
★ collecting and displaying errors, warnings
Error checking
★ checking static constraints and reporting errors
Type analysis
★ computing types of expressions
Name resolution
★ disambiguation of names
Reference resolving
★ linking identifiers to declarations
8. Consistency Checking: Generic Approach
Rename
★ make identifiers unique
Map
★ map identifiers to declarations
Project
★ compute properties of declarations, expressions
Check
★ check constraints
11. Error Checking Rules
check :
context -> (target, error)
where assumption
where require(constraint)
require(s) = not(s)
– Context: identifying points in the code to check
– Assumptions: only report an error if certain assumptions hold (validating the context and avoiding spurious errors)
– Constraints: checking for constraints at the context
– Formulating an error message
– Attribution of the error to a particular character range in the source text (usually, only part of the context
12. Error Checking: Binary Operators
check :
e@BinOp(e1, op, e2) ->
(e, $[operator [op] not defined for [<pp>t1] and [<pp>t2]])
where t1 := <type-of> e1
where t2 := <type-of> e2
where require(<type-of> e)
14. Origin Tracking
check :
e@BinOp(e1, op, e2) ->
(e, $[operator [op] not defined for [<pp>t1] and [<pp>t2]])
where ...
Assign(
Var("x")
, BinOp(
IntLit("2")
, "+"
, BinOp(IntLit("3"), "+", StringLit("4"))
)
)
Assign(
Var("x")
, Plus(IntLit("2"), Times(IntLit("3"), StringLit("4")))
)
15. Error Checking: Control-Flow Statements
check :
While(e, b) -> (e, $[Expression should have type Bool])
where t := <type-of> e
where require(<eq>(t, SimpleType("Bool")))
check :
If(e, b1, b2) -> (e, $[Expression should have type Bool])
where t := <type-of> e
where require(<eq>(t,SimpleType("Bool")))
check :
For(x, t, e, elem*) -> (e, $[[<pp>SetType(t)] expected])
where t2 := <type-of> e
where require(<eq>(t2,SetType(t)))
check rules follow the same pattern: type analysis + local consistency check
23. Type Analysis: What is Type of Variable?
define page root(x : Int) {
action exptest() {
for(y : Int in {1,2,x}) {
x := x + y;
}
}
type-of :
}
Var(x) -> t
where t := ???
Assign(
Var("x")
, BinOp(Var("x"), "+", Var("y"))
)
type of variable not part of variable use
24. Variables: Map
declare-all =
alltd(declare)
declare :
Param(x, t) -> Param(x, t)
with rules(
TypeOf : x -> t
)
type-of :
Var(x) -> t
where t := <TypeOf> x
25. Scope
define page root(x : Int) {
action exptest() {
for(x : Int in {1,2,x}) {
print(x);
}
}
}
multiple occurrences of same identifier corresponding to different declarations
26. Variables: Map + Rename
rename-all = alltd(rename)
rename :
Param(x, t) -> Param(y, t)
with y := <rename-var>(x, t)
unique annotation
rename-var :
(x, t) -> y
with y := x{<new>};
map variable to type
rules(
TypeOf : y -> t
RenameId : x -> y
)
rename occurrences
rename :
Var(x) -> Var(y) where y := <RenameId> x
type-of :
Var(x) -> t where t := <TypeOf> x
27. Term Annotations
t{t1,...,tn}
add additional information to term without affecting signature
28. Variables: Check
check :
e@Var(x) -> (e, $[Variable '[x]' not declared])
where require(<type-of>e)
29. Variable Binding Constructs
rename :
For(x, t, e1, stat1*) -> For(y, t, e2, stat2*)
with e2 := <rename-all> e1
with {| RenameId
: y := <rename-var>(x, t)
; stat2* := <rename-all> stat1*
|}
For defines local variable x in body stat1*’
30. Assignment
is-lvalue =
?Var(_) <+ ?PropertyAccess(_, _)
check :
Assign(e1, e2) -> (e1, $[Left-hand side of assignment should
be variable or property access])
where require(<is-lvalue> e1)
check :
Assign(e1, e2) -> (<id>, $[Type of lhs ('[<pp>t1]') does not
match type of rhs ('[<pp>t2]')])
where t1 := <type-of>e1
where t2 := <type-of>e2
where require(<eq>(t1, t2))
32. Rename, Map, Project, Check
Rename
★ make local variables unique
Map
★ variables to their type
Project
★ compute type of expressions
Check
★ check constraints using types
34. Consistency of Data Model Declarations
entity Blog {
url : String (id)
name : String (name)
posts : Set<Post>
author : User
}
entity Post {
url : String (id)
title : String (name)
text : WikiText
blog : Blog (inverse:posts)
author : User
blog : Blog
version : Int
}
35. Consistency Constraints for Data Models
Unique declarations
★ entity names unique in model
★ property names unique in entity
Valid types
★ type is either primitive types (e.g. String) or declared entity type
Inverse properties
★ should refer to existing entity with existing property
36. Rename; Map; Project; Check
Rename
★ not needed: top-level declarations have global scope
Map
★ map identifier to AST of declaration
Project
★ lookup information in declaration
Check
★ check consistency using map & project
38. Entity Declarations: Check
check :
ent@Entity(x, prop*) -> (x, $[Entity '[x]' defined more than once])
where require(<EntityDeclaration> x => ent)
check :
t@SimpleType(x) -> (x, $[Type '[x]' is not defined])
where require(<is-simple-type>t)
check :
t@SetType(type) -> (t, $[Set should have entity type as argument])
where <is-simple-type> type
where require(<is-entity-type> type)
40. Properties: Check
check:
ent@Entity(x, prop*) -> errors
where errors := <filter(check-property(|ent))> prop*
where require(<not(?[])> errors)
check-property(|ent) :
Property(name, type, annos) -> (name,
$[Property '[name]' defined more than once])
where require(<type-of><lookup-property(|name)>ent => type)
41. Inverse Property: Check
check-property(|ent) :
prop@Property(f, t, annos) -> (g, $[Inverse relation requires entity type])
where Inverse(g) := <inverse>prop
where tc := <carrier-type> t
where <is-simple-type> tc
where require(<is-entity-type> tc)
42. Inverse Property: Check
check:
ent@Entity(x, prop*) -> errors
where errors := <filter(check-property(|ent)); not(?[])> prop*
check-property(|ent) :
Property(f, t, annos) -> (g, $[Inverse relation requires entity type])
where Inverse(g) := <inverse>
where tc := <carrier-type> t
where <is-simple-type> tc // non-existing type already produces error message
where require(<is-entity-type> tc)
check-property(|ent1) :
Property(f, t, annos) -> (g, $[Entity '[<pp>tc]' has no property '[g]'])
where Inverse(g) := <inverse>
where tc := <carrier-type> t
where <is-entity-type> tc
where require(<lookup-property(|g)> tc)
check-property(|ent) :
Property(f, t, anno*) -> (g, $[Type of '[<pp>t1].[g]' should be [<pp>t3] or [<pp>SetType(t3)]])
where Inverse(g) := <inverse>
where t1 := <carrier-type> t
where t2 := <lookup-property(|g); type-of; carrier-type> t1
where t3 := <type-of>ent
where require(<eq>(t2, t3))
multiple check rules necessary to check different cases
43. Property References
type-of :
PropertyAccess(e, f) -> <type-of; lookup-property(|f); type-of> e
check :
e1@PropertyAccess(e2, f) -> (f, $[[<pp>t] has no property '[f]])
where t := <type-of> e2
where require(<type-of>e1)
49. Template Definitions: Check Uniqueness
check :
def@TemplateDef(mod*, x, param*, elem*) ->
(x, $[Multiple definitions for page '[x]'])
where <is-page-def> def
where require(<Template> x => def)
check :
def@TemplateDef(mod*, x, param*, elem*) ->
(x, $[Multiple definitions for template with signature [sig]])
where not(is-page-def)
where require(<declaration-of> def => def)
where sig := <signature-of;pp-sig> def
50. Checking Template/Page/Function Calls
List of expressions consistent with list of types
★ zip
Multiple possible error causes
★ call of non-existing definition
★ parameter arity mismatch
★ argument type mismatch
Argument checking reusable
51. Templates: Check Page References
check :
PageRef(x, e*) -> (x, $[Navigation to non-existing page])
where require(declaration-of)
check :
PageRef(x, e*) -> [(x, $[Navigation to template '[x]' (not a page)])]
where def := <declaration-of>
where require(<is-page-def> def)
check :
PageRef(x, e*) -> <check-args>
53. Templates: Check Template Calls
check :
Call(x, e*, elem*) -> (x, $[Template '[x]' is not defined])
where not(<is-primitive-template> x)
where require(<Template> x)
check :
Call(x, e*, elem*) -> (x, $[No definition for template with
signature '[x]([<map(type-of);pp> e*])'])
where not(<is-primitive-template> x)
where <Template> x
where require(declaration-of)
constraint-warning :
Call(x, e*, elem*) -> [(x, $[Page definition is used as template])]
where def := <declaration-of>
where require(not(<is-page-def> def))
check :
Call(x, e*, elem*) -> <check-args>
54. Checking Call Arguments
check-args =
!(<call-of>, <declaration-of>);
(check-arg-types <+ check-args-arity)
check-arg-types :
((f, e*), def) -> errors
where errors := <zip; filter(check-arg); not(?[])> (e*, <param-types> def)
check-arg :
(e, t) -> (e, $[Argument of type '[<pp>t]' expected (not of type '[<pp>t2]')])
where t2 := <type-of> e
where require(<eq>(t, t2))
check-args-arity :
((f, e*), def) -> [(f, $['[f]' expects [<int-to-string>l] arguments;
[<int-to-string>k] provided])]
with k := <length>e*
with l := <param-types; length> def
where require(<eq>(k, l))
58. From Use to Declaration
editor-resolve:
(SimpleType(type), position, ast, path, fullpath) -> target
where
Entity(target,_) := <EntityDeclaration> type
editor-resolve:
(ref@PageRef(x,e*), position, ast, path, fullpath) -> target
where
TemplateDef(_,target,_,_) := <declaration-of> ref
59. Schedule
Case 3
★ Syntax definition & term rewriting
★ Deadline: May 4
Design 2
★ Make a proposal (can be submitted separately)
★ Deadline: May 5
Lab this week
★ Finish Case 3
★ Syntax for Design 2
Next
★ Lecture 10: code generation