Symbolic Logic:Programming:Language Transformations

From Knowino
Jump to: navigation, search

There are a number of standard language transformations that allow languages to be converted to other languages.

These transformations explain the relationship between languages.

Contents

[edit] Abstract Syntax Tree Transformation

The syntax for a language describes the set of strings that are structurally legal in a language. In BNF the syntax for a simple expression may be written as:

<expression> ::= <term> "+" <expression> | <expression> "=" <term>
<term>       ::= <factor> "*" <term> | <factor>
<factor>     ::= <number> | <variable> | "(" <expression>

with appropriate definitions for the number and name functions. The equivalent desciption in mathematical logic is,

expression() = term() +  \! "+" + expression() \or expression() = term() \!
term() = factor() + \! "*" + term() \or term() = factor() \!
factor() = number() \or factor() = variable() \or factor() = \! "(" + expression() + \! ")"

When you call expression() the resulting value is the value set of of all expressions in this simple language. For example you could write,

expression() =  \! "x + y * (5 + 6)"

which would evaluate to true.

But this tells you nothing about the syntactic structure of the language. The syntactic structure identifies what part of the string has what role to play. An Abstract Syntax Tree gives this extra information. For this we need classes representing the nodes in the Abstract Syntax Tree.

class Expression; class Term; class Factor;
class Expression1 : Expression
{
private:
    Term term;
    Expression expression;
public:
    string t()
    {
        term.t() + "+" + expression.t();
    }
class term1 : Term
{
private:
    Factor factor;
    Term term;
public:
    string t()
    {
        factor.t() + "*" + term.t();
    }
}
class Factor1 : Factor
{
private:
    Number number;
public:
    string t()
    {
        numbet.t();
    }
}
class Expression2 : Expression
{
private:
    Term term;
public:
    string t()
    {
        term.t();
    }
}
class Term2 : Term
{
private:
    Factor factor;
public:
    string t()
    {
        factor.t();
    }
}
class Factor2 : Factor
{
private:
    Name name;
public:
    string t()
    {
        name.t();
    }
}
class Factor3 : Factor
{
private:
    Expresssion expression;
public:
    string t()
    {
        "(" + expression.t() + ")"
    }
}

[edit] Scope Transformation

For example,

C++ Scope transform Role transform
namespace X
{
    void swap(long x, long y)
    {
        long t = x;
        x = y;
        y = t;
    }
}
 
void main()
{
    long x = 5;
    long y = 6;
    x = x + 1;
    X::swap(x, y);
    printf("%ld, %ld", x, y);
}
void X_swap(long X_swap_x, long X_swap_y)
{
    long X_swap_t = X_swap::x;
    X_swap_x = X_swap_y;
    X_swap_y = X_swap_t;
}
 
void main()
{
    long x = 5;
    long y = 6;
    x = x + 1;
    X_swap(x, y);
    printf("%ld, %ld", x, y);
}
void swap( long X_swap_x_1    // input role for x
         , long &X_swap_x2    // output role for x
         , long X_swap_y_1    // input role for y
         , long &X_swap_y_2   // output role for y)
{
    long X_swap_t_1 = X_swap_x_1;
    X_swap_x_2 = X_swap_y_1;
    X_swap_y_2 = X_swap_t_1;
}
 
void main()
{
    long x_1 = 5;
    long y_1 = 6;
    x_2 = x_1 + 1;
    X_swap(x_2, x_3, y_1, y_2);
    printf("%ld, %ld", x_3, y_2);
}

In logic,

Xswap( Xswapx_1, Xswapx_2, Xswapy_1, Xswapy_2) \!
\implies Xswapt_1 = Xswapx_1 \and Xswapx_2 = Xswapy_1 \and Xswapy_2 = Xswapt_1 \!
x_1 = 5 \!
y_1 = 8 \!
x_2 = x_1 + 1 \!
Xswap(x_2, x_3, y_1, y_2) \!

Simplifies to,

Xswap( Xswapx_1, Xswapx_2, Xswapy_1, Xswapy_2) \!
\implies Xswapx_2 = Xswapy_1 \and Xswapy_2 = Xswapx_1 \!
y_1 = 8 \!
x_2 = 6 \!
Xswap(x_2, x_3, y_1, y_2) \!

so,

    printf("%ld, %ld", x_3, y_2);

becomes,

    printf("%ld, %ld", 8, 6);

[edit] Scope Rules

By considering only the details of the language relevant to the scope transformation, the description can be made simpler and more general. A program in a language is simplified down as to be,

An elemented is represented as e(v) \! where v is the vector of sub elements.

The scope transsformation uses the parameters,

The rules for traversing the program are defined by the scope function,

scope(T, N, e(v)) = e(role(T, N, v)) \!
role(T, N, x|v) = role(T, N, x) | role(T, N, v)) \!

Any of the scope statements,

Header text Header text Header text
scope MyScope
 {
      ...
 }
class MyClass
 {
      ...
 }
long MyFunction()
 {
      ...
 }


adds MyScope/MyClass/MyFunction to the name list describing the current scope.

A statement that adds to the scope is represented as,

sst(n, v) \!

The rule for a scope statement is,

scope(T, N, sst(n, v)) = sst(scope(T, n|N, v)) \!

A class or function declaration that adds to the scope and declares a name is represented as,

dec(n, s, o, v) \!

where

The rule for a declaration statement is,

scope(T, N, dec(n, s, o, v)) = dec(scope(T:=(FullSignature(N, s), o, n|N, v)) \!

[edit] Non standard feature transformations

There are some language features that are not naturally consistent with logic,

[edit] Role transformations

A role is the name for a variable that acts, in the role, at that point in the program.

In an imperative language a "variable" does not identifier a single value (or value set). The same "variable" identifies different values at different points in the program.

In fact, a "variable" in an imperative programming language is not a variable, it is a role. A role may have an input variable and an output variable. The output variable becomes the input variable for a role in the next statement in the program.

A role transformation converts a program written using roles into a program using variables. In an imperative program all "variables" (other than member variables) are in fact roles. A role transformation converts an imperative program into a logical/functional program.

A logical/functional program is a program that, after Scope Transformation, has for each variable a single set of values (a value set) for every occurrence of the variable.

A role is a name that represents different variables at different points in the program. In each function call a role actual parameter (for a reference formal parameter) represents two variables; an input variable and an output variable. The output variable for a role is the input variable for the next occurrence of the role.

A simple example demonstrates the transformation,

Role Variable
    void f(X &x);
 
    f(y);
    f(y);
    void f(X x1, X &x2);
 
    f(y1, y2);
    f(y2, y3);

[edit] Example

C++ Scope transform Role transform
namespace X
{
    void swap(long x, long y)
    {
        long t = x;
        x = y;
        y = t;
    }
}
 
void main()
{
    long x = 5;
    long y = 6;
    x = x + 1;
    X::swap(x, y);
    printf("%ld, %ld", x, y);
}
void X.swap(long &x, long &y)
{
    long t = x;
    x = y;
    y = t;
}
 
void main()
{
    long x = 5;
    long y = 6;
    x = x + 1;
    X.swap(x, y);
    printf("%ld, %ld", x, y);
}
void X.swap( long x_1      // input role for x
           , long &x_2    // output role for x
           , long y_1     // input role for y
           , long &y_2    // output role for y)
{
    long t_1 = x_1;
    x_2 = y_1;
    y_2 = t_1;
}
 
void main()
{
    long x_1 = 5;
    long y_1 = 6;
    x_2 = x_1 + 1;
    X.swap(x_2, x_3, y_1, y_2);
    printf("%ld, %ld", x_3, y_2);
}

In logic,

\forall x_1, x_2, y_1, y_2: X.swap( x_1, x_2, y_1, _2) \!
\implies t_1 = x_1 \and x_2 = y_1 \and y_2 = t_1 \!
x_1 = 5 \!
y_1 = 8 \!
x_2 = x_1 + 1 \!
X.swap(x_2, x_3, y_1, y_2) \!

Simplifies to,

\forall x_1, x_2, y_1, y_2: X.swap( x_1, x_2, y_1, y_2) \!
\implies x_2 = y_1 \and y_2 = x_1 \!
y_1 = 8 \!
x_2 = 6 \!
X.swap(x_2, x_3, y_1, y_2) \!

so,

    printf("%ld, %ld", x_3, y_2);

becomes,

    printf("%ld, %ld", 8, 6);

[edit] State

The state S\! maps roles to variables. It is a set of tuples. The expression S:=r \! is a new state with a new unique variable name assigned to r. Mathematically,

(x, v) \in S \and x = r \implies (r, next(v)) \in S:=r \!
(x, v) \in S \and x \ne r \implies (x, v) \in S:=r \!

next(v)\! is a new unique variable, constructed from v. For example there may be a series of names,

x_1, x_2, x_3, ... \!

S[r] \! gives the variable associated with a role r \! in a state S \!.

[edit] Role

By considering only the details of the language relevant to the role transformation, the description can be made simpler and more general. A program in a language is simplified down as to be,

An elemented is represented as e(v) \! where v is the vector of sub elements. The rules for traversing the program are defined by the role function,

role(S_i, S_o, e(v)) = e(role(S_i, S_o, v)) \!
role(S_i, S_o, x|v) = role(S_i, S_m, x) | role(S_m, S_o, v)) \!

As you can see the order of the elements is the order used by the role transformation.

An actual parameter for a reference parameter is writen,

apr(t) \!

The rule for a reference parameter is,

S_o = S_i:=y \and role(S_i, S_o, [apr(y)]) = [apr(S_i[y]), apr(S_o[y])] \!

If the element is none of the above the exception condition applies,

\neg exc_r(o) \and role(S, S, o) = o \!

where,

exc_r(o) = ( o = fpr(x) \or o = apr(y) \or o = f(p, b) ) \!

[edit] Functions and Formal Parameters

An element can be a function declaration,

f(p, b) \!

where f \! is the function name, p \! is the list of parameters, and b \! is the body.

The role transformation for a function declaration is,

role(Q, Q, f(p, b)) = f(params(S_i, S_o, p), role(S_i, S_o, b,))  \!

The rules for transforming parameters are,

params(S_i, S_o, x|p) = params(S_i, S_o, x) + params(S_i, S_o, p) \!

A role formal parameter that is a reference parameter is written,

fpr(T, t) \!

A formal parameter is defined by,

params(S_i, S_o, fpr(Y, y)) = [ fpr(Y, S_i[y]), fpr(Y, S_o[y]) ] \!

The default rule is,

\neg exc_v(z) \and params(S_i, S_o, z) = [z] \!
exc_v(z) = (z = x|p \or z=fpr(Y, y)) \!

[edit] Member Variables

Member transform differently to other variables in a role transfornations.

!!! to be completed !!!

[edit] Example

[edit] Equivalent Features

The following table shows the correspondence between imperative language C++ and logic. This is a fairly informal description. A more accurate description, would be that, after applying the transformations described above these features are equivalent. This table is intended as a guide.

Id Description C++ Description Logic
1 boolean function bool f(P p) {return g(p);} f(p) implies g(p) p \in P \and f(p) \implies g(p) \!
2 method void f(P p) {g(p);} f(p) implies g(p) p \in P \and f(p) \implies g(p) \!
3 function T f(P p) {return g(p);} t = f(p) implies t = g(p) p \in P \and t \in T \and t = f(p) \implies t = g(p) \!
4 function T f(P p) {h(p); return g(p);} t = f(p) implies h(p) and t = g(p) p \in P \and t \in T \and t = f(p) \implies h(p) \and t = g(p) \!
5 result = x return x t = x \!
6 statements A; B A and B A \and B \!
7 assignment a = b; the output role a = the input role b a_{n+1} = b_n \!
8 reference parameter f(T &t) input role + output role t_i \in T \and t_o \in T \and f(t_i, t_o) \!

[edit] Links

Personal tools
Variants
Actions
Navigation
Community
Toolbox