Skip to content

Repository files navigation

* PyHask
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.
* User's manual
** Language's philosophy
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.
** How to run PyHask
After cloning the repository please build it using:
#+BEGIN_SRC sh
stack build
#+END_SRC

After that source programs must be first compiled and the generated output can be executed in the following way
#+BEGIN_SRC sh
stack exec PyHask-exe compile example.ph
stack exec PyHask-exe execute example.phc
#+END_SRC

Please refer to [[https://docs.haskellstack.org/en/stable/README/][Stack]] for more information related to the Haskell tool stack and how to use it.
** Primitive types
This language supports ~int~, ~float~, ~char~ and ~bool~ as primitive types.
** Variable declarations
*** Primitive declaration
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.
**** Default values
- ~int~  : ~0~
- ~float~ : ~0.0~
- ~char~ : ~a~
- ~bool~ : ~True~
**** Valid declaration with default value
~let a : int := 10~
**** Valid declaration no default value
~let a : int~
**** Invalid declaration
~let a~
*** Array declaration
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.
**** Valid array declaration with one dimension
~let a : int[5]~
**** Valid array declarations with more than one dimensions
- ~let a : int[5][6]~
- ~let b : bool[3][9][10]~
*** Object declaration
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.
**** Valid object declaration
~create h : Home(10,5.0)~
** Control flow structures
*** Conditionals
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.
**** Valid conditonal - only if block
#+BEGIN_SRC python
if 5 < 2:
  print(1)
#+END_SRC
**** Valid conditional - with multiple elif blocks
#+BEGIN_SRC python
if 5 == 3:
  print(1)
elif 2 < 3:
  print(2)
elif 5 == 5:
  print(3)
#+END_SRC
**** Valid conditional - with an else block
#+BEGIN_SRC python
if 5 == 3:
  print(1)
else
  print(2)
#+END_SRC
*** While loop
PyHask supports while loops the Python way, by using the keyword ~while~ followed by a boolean expression and a block of statements.
**** Valid while loop
#+BEGIN_SRC python
while True:
  print(3)
#+END_SRC
*** For loop
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.
**** Valid for loop
#+BEGIN_SRC python
for i : int := 0 : True : i := i + 1:
  print(i)
#+END_SRC
** Functions
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.
*** Function with return type
#+BEGIN_SRC python
def fact(i: int) -> int:
  if i == 0:
    return 1
  return i * fact(i-1)
#+END_SRC
*** Function without a return type
#+BEGIN_SRC python
def no_return() -> void:
  print(10)
#+END_SRC
** Classes
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.
*** Simple class example
#+BEGIN_SRC python
class Home:
  init:
    __init__(i:int):
      pass

  def f(d: float) -> int:
    return 1
#+END_SRC
*** Class declaration
#+BEGIN_SRC python
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
#+END_SRC
*** Inheritance example
#+BEGIN_SRC python
class SonClass(MemberedClass):
  init:
    __init__(i: int, f: float):
      super.__init__(i,f)

  def calc() -> float:
    return super.calc()
#+END_SRC
** More examples
Please refer to the /ph/ files in the repository for more examples of PyHask

About

No description or website provided.

Topics

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages