You are on page 1of 39

HIT3155 Languages in

Software Development
Lecture 2
Semester 1, 2015
Dr. Pan Zheng

Recall what is language

Language definition can be loosely divided into:


Syntax, or structure
Semantics, or meaning

Several notational systems have been developed for language


semantics:
Operational semantics
Denotational semantics
Axiomatic semantics

Testing vs. logical reasoning

Q.E.D : quod erat demonstrandum


(that which was to be proved)

Logical reasoning

Axioms:The set of facts we


have to work with.

Theorems:Built from our axioms


based on inference/
deduction rules.

Deductive Logic: Detachment


,

Ryan Gosling Look good, Ryan Gosling


Look good

Deductive logic: syllogism


, ,

Ryan Gosling Great hair,Great hair Look good, Ryan Gosling


Look good

The Hilbert-style Proof System

A Hilbert-style proof system consists of axioms and proof rules:

An axiom of a proof system is a formula that is provable by


definition.

An inference rule asserts that if some list of formulae is


provable, then so is another formula.

A proof is a structured object built from formulae according to


constraints established by a set of axioms and inference rules.

The Hilbert-style Proof System

The rule format:

We construct a proof from proofs:

Axiomatic Semantics

The axiomatic semantics is a formal (proof) system for deriving


equations between expressions.
it describes only what a program does

The basic idea of the axiomatic method is to define the


meaning of language elements indirectly using logical
assertions.

For example, we can write

{P}Q{R}
called a Hoare triple, to state that if the Boolean expression P holds prior the

computation of Q, and if Q terminates, then the Boolean expression R must


hold as well.

Hoare Triple

{P}Q{R}

Precondition

Program

what needs to be satisfied


in order for everything to be true, specifies what
the program expects before execution

Postcondition

what is true if the precondition


is satisfied AND the program
executes.

If Pre holds before executing Q, and Q terminates, then R holds after Q .

In

other words, if we start with a store in which Pre holds and


the execution of Q with respect to terminates and yields a store
, then Post holds in store

Hoare Triple

Pre-conditions and post-conditions can be regarded as


interfaces or contracts between the program and its clients

They help users to understand what the program is supposed


to yield without needing to understand how the program
executes. (like a blackbox)

Typically, programmers write them as comments for


procedures and functions as documentation and to make it
easier to maintain programs.

Such specifications are especially useful for library functions


for which the source code is often not available to the users.
serve as contracts between the library developers and users of the library

Hoare Triple

the comments describe the intent of the developer, but they do


not give a guarantee of correctness.

Axiomatic semantics addresses this problem.


It shows how to rigorously describe (partial) correctness statements

and how to establish correctness using formal reasoning.

Example of Hoarse Triples

{} = 5{ = 5}

{ = } = + 3{ = + 3}

{ > 0} = 2 { > 2}

{ = } < 0 = { = ||}

{} = 3{ = 8}

{} + 1{}

Hoarse Triples : Assignment

{P}x:=x+1{x N}

Assignment/Substitution rule
{P0}x:=f{P}
Where x is a variable identifier;
P0 is obtained from P by substituting f for all occurrences of x

so please find the precondition of this

Example: exercise
{x+1 }x:=x+1{ }
or even better
{x -1}x:=x+1{ }

Hoarse Triples :Sequence

Sequence rule

{P}x:=x+1;y:=x+y{y>5}
Refer to whiteboard ...

Hoarse Triples : Condition

Conditional rule

The if commands involves a choice between alternatives.

Two paths lead through an if command, if we can prove each


path is correct given the appropriate values of the Boolean
expression, the entire command is correct

Hoarse Triples : Condition

For example, a proof of

{0 x 15 } if x < 15 then x := x + 1 else x := 0 endif {0 x 15 }

needs to apply the conditional rule, which in turn requires to prove

{ 0 x 15 x < 15 } x:=x+1 { 0 x 15 }, or simplified

{0 x < 15 } x:=x+1 {0 x 15 }

for the then part,

AND

{0 x 15 x 15} x:=0 {0 x 15}, or simplified

{x=15} x:=0 {0 x 15 }

for the else part.

Hoarse Triples : Condition

Another example

Premise 1:

Premise 2:

Proof:

Operational Semantics

The purpose of operational semantics is to describe how a computation


is performed.

The operational semantics is based on a directed form of equational


reasoning called reduction. Reduction may be regarded as a form of
symbolic evaluation.

The basic idea of the operational method is to define the meaning of the
language elements by means of a (labelled) transition system.

The operational semantics definition provides means to display the


computation steps undertaken when a program is evaluated to its output.

Some forms of operational semantics are interpreted-based, with


instruction counters, data structures, and the like, and others are
inference rule-based, with proof trees that show control flows and data
dependencies.

Operational Semantics

Denotational Semantics

The denotational semantics, or model theory, is defined in the spirit of


equational logic or first-order logic. A denotational semantics definition
(model) consists of a family of sets, one for each type, with the property
that each well-typed expression may be interpreted as a specific element
of the appropriate set.

The denotational semantics is a recursive definition that maps well-typed


derivation trees to their mathematical meanings. For example, the set
Bool consists of two meanings: Bool = {true, false} and an operation

not : Bool Bool with not(false) = true, not(true) = false.

The denotational method does not maintain states, but the meaning of a
program is given as a function that interprets all language elements of a
given program as elements of a corresponding set of values.

Denotational Semantics

Types and Type Systems

Types are collections of values that share some common properties. When we
say that v is a value of type T, we mean that v T.

In some systems, there may be types with types as members. Types with types
as members are usually called something else, such as universes, orders, or
kinds, to avoid the impression of circularity.

In a type system, types provide a division or classification of some universe of


possible values. A type system defines in a mathematical way (axioms and
deduction-rules), which expressions are typable,
i.e., which expressions can be assigned a valid type using the underlying type system.

In most programming languages, types are checked in some way, either during
program compilation, or during execution. The main purpose of type checking is
the detection of errors, documentation, program optimization, etc.

Values

In computer science we classify as a value everything that may


be evaluated, stored, incorporated in a data structure, passed
as an argument to a procedure or function, returned as a
function result, and so on.

In computer science, as in mathematics, an expression is


used (solely) to denote a value.

Which kinds of values are supported by a specific


programming language is heavily depended on the underlying
paradigm and its application domain.

Most programming languages share some basic sets of values


like truth values, integers, real number, records, lists, etc.

Constants

Constants are named abstractions of values.

Constants are used to assign an user-defined meaning to a value.

Examples:
EOF = -1
TRUE = 1
FALSE = 0
PI = 3.1415927
MESSAGE = Welcome to HIT3315

Constants do not have an address, i.e., they do not have a location.

At compile time, applications of constants are substituted by their


corresponding definition.

Constants

Constants are named abstractions of values.

Constants are used to assign an user-defined meaning to a value.

Examples:
EOF = -1
TRUE = 1
FALSE = 0
PI = 3.1415927
MESSAGE = Welcome to HIT3315

Constants do not have an address, i.e., they do not have a location.

At compile time, applications of constants are substituted by their


corresponding definition.

Primitive Values

Primitive values are these values that cannot further


decomposed. Some of these values are implementation and
platform dependent.

Examples:
Truth values
Integers
Characters
Strings
Real numbers

Composite Values

Composite values are built up using primitive values and


composite values. The layout of composite values is in general
implementation dependent.

Examples:
Records
Arrays
Enumerations
Sets
Lists
Tuples
Files

Pointers

Pointers are references to values, i.e., they denote locations of a


values.

Pointers are used to store the address of a value (variable or


function) pointer to a value, and pointers are also used to store
the address of another pointer pointer to pointer.

In general, it not necessary to define pointers with a greater


reference level than pointer to pointer.

In modern programming languages, we find pointers to variables,


pointers to pointer, function pointers, and object pointers, but not all
programming languages provide means to use pointers directly
(e.g., Java, Scheme).

A Language Interpreter

An interpreter consists of two parts:


A front end that converts program text (a program in the source

language)
to a abstract syntax tree (the internal representation of the program

text) and

An evaluator (the actual interpreter) that looks at a data


structure and performs some associated actions, which
depend on the actual data structure.
In case of a language-processing system, the interpreter takes the

abstract syntax tree and converts it, possibly using external inputs, to
an answer.
Examples:
A calculator, Basic, Perl, Python, sh, awk, Tcl
JVM

Execution via Interpreter

A Language Compiler

A compiler translates program text into some other language


(the target language).

The building blocks of a compiler are:


A front end that converts program text (a program in the source

language) to a abstract syntax tree (the internal representation of the


program text),
A set of independent compiler phases, each has assigned a

particular task in the compilation process (e.g. semantics analysis,


optimization, register allocation, code emission), and
The evaluator of a compiled languages may be an interpreter (e.g.

JVM) or simply a hardware machine (e.g. von Neumann computer).


Examples of compiled languages:
C/C++, C#
Pascal, Java

Execution via Compiler

Programming Language Values

In the specification of programming languages we have always


at least two sets of values:
Expressed values values that can be specified by

means of (literal) expressions in the given


programming language (result of expression)
Examples: numbers, pairs, characters, strings
Denoted values values that are bound to names

(meaning of a variable)
Examples: variables, parameters, procedures

Source, Host, and Target Language


The

source language is the language in which we write


programs that should be evaluated by an interpreter or
compiled by a compiler.

The

host language is the language in which we specify


the interpreter or compiler.

The

target language is the language a source


language in translated into by a compiler.
A target language may be a higher-level programming language

(e.g., C) or assembly language or machine language.

Compiler

Interpreter

Compiler Takes Entire program as input

Translates program one statement at a time.

Intermediate Object Code is Generated

No Intermediate Object Code is Generated

Conditional Control Statements are


Executes faster

Conditional Control Statements are


Executes slower

Memory Requirement : More(Since Object


Code is Generated)

Memory Requirement is Less

Program need not be compiled every time

Every time higher level program is converted


into lower level program

Errors are displayed after entire program is Errors are displayed for every
checked
instruction interpreted (if any)
generates the error message only after
scanning the whole program. Hence
debugging is comparatively hard.

Continues processing the program until the


first error is met, in which case it stops. Hence
debugging is easy

Interpreter

compiler

End of lecture 2

You might also like