PyHask is the project for compiler’s design class, it aims to build a small object oriented programming language using Haskell with syntax inspired on Python.
This language aims to be an imperative styled and statically typed language with support for the basic control flow structures, declaration for primitive types, declaration of N-dimensional arrays (PyHask does not impose a limit on the number of dimensions for an array), primitive based functions and basic objected oriented functionality. PyHask believes in scopes with arbitraty depth and to allow variables declared in a scope to be redeclared outside of it.
PyHask borrows most of its syntax from Python, including type annotations for which it borrows Python’s type hints. The project aims for the feel of an scripting language by not imposing the creation of a main block, and to freely allow variable declarations anywhere in the code.
After cloning the repository please build it using:
stack build
After that source programs must be first compiled and the generated output can be executed in the following way
stack exec PyHask-exe compile example.ph
stack exec PyHask-exe execute example.phc
Please refer to Stack for more information related to the Haskell tool stack and how to use it.
This language supports int
, float
, char
and bool
as primitive types.
Primivites are declared in PyHask by using the keyword let
, specifying all the variables for that type; after that it is required to specify the primitive type for the variables and optionally and initial value for the variables. if no initial value is provided a default one will be given.
int
:0
float
:0.0
char
:a
bool
:True
let a : int := 10
let a : int
let a
An array is declared also by using the keyword let
, specifying variables, and by specifying the type and dimensions of the array, arrays in PyHask are N-dimensional,
arrays declaration do not support optional initial value as assigning an entire array is currently not supported in PyHask, all the values for the array have
as initial value the default ones specified in the previous section of the document.
let a : int[5]
let a : int[5][6]
let b : bool[3][9][10]
To create an object it is necessary to first declare a class for which to instantiate an object from, this topic is gonna be covered later in the manual, in the meantime an example is gonna be given with a hypotethical class called Home
that receives a integer and a floating point value on its constructors
Object declaration uses the create
keyword instead of the let
keyword. The correct structure for object
creation is to use create
followed by the class from which the object will be instantiated, and in parenthesis
the parameters to be passed to the constructor.
create h : Home(10,5.0)
PyHask supports conditionals by means of having if
, elif
, and else
blocks. These blocks work just like in Python, with if
block optionally followed by a number of
elif
blocks and optionally an else
block as a catch all.
After the if
and elif
keywords a boolean expression must be stated to evaluate if the block is going to be executed.
if 5 < 2:
print(1)
if 5 == 3:
print(1)
elif 2 < 3:
print(2)
elif 5 == 5:
print(3)
if 5 == 3:
print(1)
else
print(2)
PyHask supports while loops the Python way, by using the keyword while
followed by a boolean expression and a block of statements.
while True:
print(3)
For loops are one of the elements where PyHask differs from Python. For loops share some similarity with C-styled loops by first having variable declarations, followed by a boolean expression and an statement.
for i : int := 0 : True : i := i + 1:
print(i)
PyHask borrows its syntax for functions from Python, even the the type declarations for functions are based on Python’s optional type hinting.
Functions are declared by first using the keyword def
followed by the name of the function and a list of parameters for the function to
receive; finally the function must mark the return type for it with ->
and setting a primitive type or the void
keyword.
def fact(i: int) -> int:
if i == 0:
return 1
return i * fact(i-1)
def no_return() -> void:
print(10)
Classes are perhaps the most complicated construct which PyHask has to offer. Again the syntax for it somewhat resembles Python’s syntax.
The class
keyword must be used to indicate the start of a class declaration, optionally followed by a parent class enclosed in parenthesis.
The class definition must be followed by an init block. Init blocks can contain member definitions and must always define a constructor named
init
. After the initialization block methods of the class can follow declared as regular functions while inside the indentantion of the class.
Methods will have access to self
referring to an instance of the object of the class for which the method belongs. Methods may have a super
variable referring to the parent of the class, this can be used to call a parent’s method and it’s specially useful in constructors to initialize the
variables the parent constructor initializes.
class Home:
init:
__init__(i:int):
pass
def f(d: float) -> int:
return 1
class MemberedClass:
init:
let member1 : int
let member2 : float
__init__(i: int, f: float):
self.member1 := i
self.member2 := f
def calc() -> float:
return self.member1 * self.member2
class SonClass(MemberedClass):
init:
__init__(i: int, f: float):
super.__init__(i,f)
def calc() -> float:
return super.calc()
Please refer to the ph files in the repository for more examples of PyHask