Compare commits

..

3 Commits

Author SHA1 Message Date
771a4b7044 Add path to binary in Jenkins 2024-07-21 18:16:34 -05:00
ee0be7635b Add docs on constructors 2024-07-21 18:06:01 -05:00
396a5b811a add doc pages 2024-07-20 22:44:42 -05:00
10 changed files with 345 additions and 142 deletions

View File

@ -16,6 +16,8 @@ pipeline {
} }
stage('Build bundle') { stage('Build bundle') {
steps { steps {
sh 'rm .env || true'
sh 'echo "THP_BINARY=/var/lib/jenkins/bin/thp" > .env'
sh 'pnpm build' sh 'pnpm build'
} }
} }

View File

@ -86,7 +86,11 @@ export async function native_highlighter(code: string): Promise<string> {
} }
function translate_token_type(tt: TokenType, value: string): string { function translate_token_type(tt: TokenType, value: string): string {
const keywords = ["throws", "extends", "constructor", "case", "static", "const", "enum", "union", "loop", "use", "break", "catch", "continue", "as", "do", "else", "finally", "for", "fun", "if", "in", "fn", "nil", "return", "throw", "try", "while", "type", "match", "with", "of", "abstract", "class", "interface", "private", "pub", "override", "open", "init", "val", "var", "mut", "clone"]; const keywords = ["throws", "extends", "constructor", "case", "static", "const",
"enum", "union", "loop", "use", "break", "catch", "continue", "as", "do",
"else", "finally", "for", "fun", "if", "in", "fn", "nil", "return", "throw",
"try", "while", "type", "match", "with", "of", "abstract", "class", "interface",
"private", "protected", "pub", "override", "open", "init", "val", "var", "mut", "clone"];
switch (tt) { switch (tt) {
case "Datatype": case "Datatype":

View File

@ -0,0 +1,9 @@
---
layout: ../../../layouts/DocsLayout.astro
title: Abstract
---
import Code from "../../../components/Code.astro"
# Abstract

View File

@ -0,0 +1,163 @@
---
layout: ../../../layouts/DocsLayout.astro
title: Constructor/Destructor
---
import Code from "../../../components/Code.astro"
# Constructor/Destructor
## Constructor
The constructor syntax in THP is inspired by Kotlin.
Constructors are declared like function definitions:
<Code thpcode={`
// |this is the constructor |
class Animal(String fullname, Int age)
// Creating an instance
val cat = Animal("Michi", 3)
`} />
A constructor declared that way is public.
Note that the parameters in the constructor (`fullname`,
`age` above) are not properties, and cannot be used
inside the class methods, only in the
[`init` block](#init-block) and properties declaration.
To declare properties in the constructor see
[Constructor promotion](#constructor-promotion).
### Constructor visibility
If you want to declare a constructor as protected
or private you need to add the `constructor`
keyword, after the visibility modifier:
<Code thpcode={`
// Cow has a protected constructor
class Cow
protected constructor(String color)
// Bat has a private constructor
class Bat
private constructor(Int height)
`} />
### Init block
The `init` block allow us to run code during the
construction of the instance:
<Code thpcode={`
class Dog(String name)
{
pub String name = name
Int name_len = name.length
init
{
print("Dog created: {name}")
}
}
`} />
### Constructor promotion
Constructor parameters can serve as class properties.
This is done by adding a modifier and `var`/`val`.
<Code thpcode={`
class Parrot(
// A public property
pub val String name,
// A protected property
protected var Int age,
// A private property
var String last_name,
)
`} />
By using this syntax you are declaring properties and assigning them
at the same time.
The contructor parameters can also have default values.
### Derived properties
You can declare properties whose values depend on values
on the constructor.
<Code thpcode={`
class Animal(
val String fullname,
)
{
// A property whose value depends on \`fullname\`
// This is executed after the contructor
pub val Int name_length = fullname.length
}
val a2 = Animal("Doa")
print(a2.name_length) //: 3
`} />
### Constructor that may fail
TBD
Proposal 1:
<Code thpcode={`
class PrayingMantis(String name) -> self!Error
`} />
Proposal 2:
<Code thpcode={`
class PrayingMantis(String name)
throws Error
`} />
Proposal 3:
<Code thpcode={`
class PrayingMantis(String name)
{
init -> self!Error
{
// Something that may fail
}
}
`} />
## Destructor
The destructor in THP is the same as PHP.
<Code thpcode={`
class Owl
{
pub fun __destruct()
{
// Cleanup
print("Destroying Owl...")
}
}
`} />

View File

@ -1,6 +1,6 @@
--- ---
layout: ../../../layouts/DocsLayout.astro layout: ../../../layouts/DocsLayout.astro
title: Classes title: Basics
--- ---
import Code from "../../../components/Code.astro" import Code from "../../../components/Code.astro"
@ -8,30 +8,34 @@ import Code from "../../../components/Code.astro"
Syntax and semantics heavily inspired by Kotlin. Syntax and semantics heavily inspired by Kotlin.
Classes in THP are significantly different than PHP.
## Create a new instance of a class ## Definition
To create an instance of a class call it as if it were a function, A class is defined as follows:
<Code thpcode={`
class Animal
`} />
The name of the class **MUST** begin with an uppercase letter.
## Instanciation
To create an instance of a class call it as if it was a function,
without `new`. without `new`.
<Code thpcode={` <Code thpcode={`
val animal = Animal() val animal = Animal()
`} /> `} />
## Simple class
Classes are declared with the `class` keyword.
<Code thpcode={`
class Animal
val instance = Animal()
`} />
## Properties ## Properties
Properties are declared with `var`/`val`. Properties are declared with `var`/`val` inside a block.
They **must** declare their datatype. They **must** explicitly declare their datatype.
<Code thpcode={` <Code thpcode={`
class Person class Person
@ -42,11 +46,13 @@ class Person
// This is correct // This is correct
val String name = "Jane Doe" val String name = "Jane Doe"
// This is also okay
String name = "Jane Doe"
} }
`} /> `} />
Properties are private by default, **Properties are private by default**, but can be made public with `pub`.
but can be made public with `pub`.
<Code thpcode={` <Code thpcode={`
class Person class Person
@ -57,10 +63,22 @@ class Person
// To make a property public use \`pub\` // To make a property public use \`pub\`
pub var Int age = 30 pub var Int age = 30
} }
val p = Person()
print(p.name) // Compile error: \`name\` is private
print(p.age) // 30
`} /> `} />
More information about how properties interact with the constructor Unlike PHP, to access properties and methods use dot notation `.`
is found in the contructor section. instead of an arrow `->`.
Static properties are explained in the Static page.
Readonly properties are explained in the Readonly page.
The interaction between properties and the constructor is explained
in the Constructor page.
## Methods ## Methods
@ -77,7 +95,7 @@ class Person
} }
`} /> `} />
Methods are private by default, and are made public with `pub`. **Methods are private by default**, and are made public with `pub`.
<Code thpcode={` <Code thpcode={`
class Person class Person
@ -100,10 +118,27 @@ p.greet() //: Hello from greet
p.private_greet() // Compile time error. Private method. p.private_greet() // Compile time error. Private method.
`} /> `} />
[Unlike PHP](https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.properties-methods),
in THP a method cannot have the same name as a property and viceversa.
Doing so is a compile error.
<Code thpcode={`
class Person
{
String name = "Rose"
// This is a compile error
fun name() -> String {
"Rose"
}
}
`} />
## This ## This
THP uses the dollar sign `$` as this. It is **required** when THP uses the dollar sign `$` as this inside classes.
using a class property/method. It is **required** when using a class property/method.
<Code thpcode={` <Code thpcode={`
class Person class Person
@ -123,126 +158,6 @@ class Person
} }
`} /> `} />
## Static members
Static members are detailed in their own page.
## Constructor
(for now) THP's constructors are inspired by Kotlin.
PHP only allows a single constructor, and so does THP.
The basic constructor has the syntax of function parameters.
<Code thpcode={`
// |this is the constructor |
class Animal(String fullname, Int age)
val a1 = Animal("Nal", 4)
`} />
The class properties can be declared in the constructor,
using the keywords `pub`, `var`, `val`:
<Code thpcode={`
class Animal(
// Since we are using val/var, these are promoted to class properties
val String fullname,
var Int age,
)
{
pub fun say()
{
// Here we are using the properties declared in the constructor
print("My name is {$fullname} and i'm {$age} years old")
}
}
val a1 = Animal("Nal", 4)
a1.say() //: My name is Nal and i'm 4 years old
`} />
By using this syntax you are declaring properties and assigning them
at the same time.
The contructor parameters can also have default values.
### Constructor visibility
The constructor is public by default. It can be made private/protected
like this:
<Code thpcode={`
class Animal
private constructor(
val String fullname,
var Int age,
)
{...}
`} />
### Derived properties
You can declare properties whose values depend on values
on the constructor.
<Code thpcode={`
class Animal(
val String fullname,
)
{
// A property whose value depends on \`fullname\`
// This is executed after the contructor
pub val Int name_length = $fullname.length
}
val a2 = Animal("Doa")
print(a2.name_length) //: 3
`} />
### Init block
If you need to additional logic in the constructor you can
use a `init` block.
<Code thpcode={`
class Animal(
val String fullname,
)
{
init
{
print("{$fullname} in contruction...")
}
}
val a3 = Animal("Lola") //: Lola in construction
`} />
## Inheritance
<Code thpcode={`
// Base class
class Animal(var String name)
{
pub fun say_name()
{
print($name)
}
}
// Child class
class Cat(String name, Int lives)
extends Animal(name)
Cat("Michi", 9).say_name()
`} />
## Mutable methods ## Mutable methods

View File

@ -0,0 +1,26 @@
---
layout: ../../../layouts/DocsLayout.astro
title: Inheritance
---
import Code from "../../../components/Code.astro"
# Inheritance
<Code thpcode={`
// Base class
class Animal(var String name)
{
pub fun say_name()
{
print($name)
}
}
// Child class
class Cat(String name, Int lives)
extends Animal(name)
Cat("Michi", 9).say_name()
`} />

View File

@ -0,0 +1,7 @@
---
layout: ../../../layouts/DocsLayout.astro
title: Readonly
---
import Code from "../../../components/Code.astro"
# Readonly

View File

@ -0,0 +1,7 @@
---
layout: ../../../layouts/DocsLayout.astro
title: Visibility
---
import Code from "../../../components/Code.astro"
# Visibility

View File

@ -44,7 +44,12 @@ pagesLayout:
title: Classes title: Classes
children: children:
- path: definition - path: definition
- path: constructor
- path: inheritance
- path: static - path: static
- path: visibility
- path: readonly
- path: abstract
- path: interfaces - path: interfaces
- path: anonymous - path: anonymous
- path: magic - path: magic

View File

@ -7,3 +7,68 @@ import Info from "../../../components/docs/Info.astro"
# Control flow # Control flow
## If expressions
Use `@if`, `@else if` and `@else` to branch during the template
creation.
<Code thpcode={`
fun User(User user) -> HTML
{
<div>
@if user.verified
{
<p>Hello {user.name}</p>
}
@else
{
<p>Verify your account to continue</p>
}
</div>
}
`} />
## Loops
Use `@for`:
<Code thpcode={`
fun Users() -> HTML
{
val users = User::get_all()
<div>
@for user in users
{
<User user={user} />
}
</div>
}
`} />
## Match
Use `@match` for pattern matching:
<Code thpcode={`
fun UserDetail(User user) -> HTML
{
<div>
@match user.type
case ::Admin
{
<button>Delete resource</button>
}
case ::User
{
<button disable>Not allowed</button>
}
</div>
}
`} />