Improve landing page
This commit is contained in:
parent
5f5ae25060
commit
cb5b87488a
51
md/learn/adts/union-types.md
Normal file
51
md/learn/adts/union-types.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Union types
|
||||
|
||||
## Basic enums
|
||||
|
||||
```thp
|
||||
enum Suit
|
||||
{
|
||||
Hearts,
|
||||
Diamonds,
|
||||
Clubs,
|
||||
Spades,
|
||||
}
|
||||
|
||||
val suit = Suit::Hearts
|
||||
```
|
||||
|
||||
|
||||
## Enums with values
|
||||
|
||||
```thp
|
||||
enum IpAddress
|
||||
{
|
||||
V4(String),
|
||||
V6(String),
|
||||
}
|
||||
|
||||
val addr_1 = IpAddress::V4("192.168.0.1")
|
||||
|
||||
match addr_1
|
||||
| IpAddress::V4(ip)
|
||||
{
|
||||
// code..
|
||||
}
|
||||
| IpAddress::V6(ip)
|
||||
{
|
||||
// more code..
|
||||
}
|
||||
|
||||
// Without the full qualifier
|
||||
match addr_1
|
||||
| ::V4(ip)
|
||||
{
|
||||
// code...
|
||||
}
|
||||
| ::V6(ip)
|
||||
{
|
||||
// even more code...
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,80 +1,28 @@
|
||||
# Comments
|
||||
|
||||
You may have noticed that in some code examples there are some
|
||||
lines of text explaining the code:
|
||||
Only these two:
|
||||
|
||||
```thp
|
||||
// This is the variable
|
||||
val person = "John"
|
||||
```
|
||||
|
||||
Comments are used to explain what the code does. Anything written
|
||||
in a comment is ignored by THP.
|
||||
|
||||
## Single line comments
|
||||
|
||||
As the name says, these comments span only 1 line. To create one write
|
||||
two slashes together `//`. Everything after the slashes and before
|
||||
the newline will be ignored.
|
||||
## Single line
|
||||
|
||||
```thp
|
||||
// This is a single line comment
|
||||
// You can write anything you want here, although it's usually
|
||||
// used to describe the code
|
||||
|
||||
// The commend ends where the line ends,
|
||||
so this line will not be ignored by THP, and will throw an error
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Multi line comments
|
||||
|
||||
As the name says, these comments can span multiple lines.
|
||||
|
||||
They have 2 components: a start and a end. To start a multiline comment
|
||||
write a slash and asterisk `/*`, and to end the comment, the inverse `*/`
|
||||
## Multi line
|
||||
|
||||
```thp
|
||||
/*
|
||||
This is a multiline comment.
|
||||
I can write whatever I want here, and across multiple
|
||||
lines, as long as I'm before the closing characters (* /)
|
||||
This is a
|
||||
multiline comment
|
||||
*/
|
||||
```
|
||||
|
||||
```thp
|
||||
/*
|
||||
Multiline comments
|
||||
can be /* nested */
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
## Using comments to prevent code execution
|
||||
|
||||
Since comments are ignored by THP, we can use them to prevent certain
|
||||
parts of the code from running.
|
||||
|
||||
Let's say we have this script:
|
||||
|
||||
```thp
|
||||
print("Hello John")
|
||||
print("How's your day going?")
|
||||
```
|
||||
|
||||
If I wanted the 2nd line not to execute, I can use a comment:
|
||||
|
||||
```thp
|
||||
print("Hello John")
|
||||
// print("How's your day going?")
|
||||
```
|
||||
|
||||
Now the second line is ignored, and the message is not printed.
|
||||
|
||||
The same can be done with multiline comments.
|
||||
|
||||
|
||||
```thp
|
||||
print("Hello John")
|
||||
/*
|
||||
print("How's your day going?")
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,127 +1,45 @@
|
||||
# Datatypes
|
||||
|
||||
Programming is comprised of 2 basic things: instructions and data.
|
||||
Datatypes's first character are always uppercase.
|
||||
|
||||
If we compare a program to a cake recipe, the instructions are the steps
|
||||
(**pour** flour, **add** water, **add** egg, **mix**) and the data are the ingredients
|
||||
themselves (flour, water, egg).
|
||||
## Int
|
||||
|
||||
![Image](Image)
|
||||
|
||||
Then, we can describe the recipe in terms of instructions and data. For example,
|
||||
"mix flour and egg to produce dough".
|
||||
|
||||
![Image](Image)
|
||||
|
||||
All code is like a recipe: A list of instructions and data that, when combined
|
||||
correctly, are able to transform a input to an output. Many advanced concepts
|
||||
are just ways to organize and abstract those instructions and data.
|
||||
|
||||
|
||||
## Classifying datatypes
|
||||
|
||||
As with food, datatypes can be classified. Just like there are fruits, vegetables,
|
||||
oils, there are `numbers`, `text`, `"booleans"`.
|
||||
|
||||
|
||||
|
||||
### Int
|
||||
|
||||
Int is an abbreviation for "integer numbers", which are numbers without a fractional component.
|
||||
They can be positive or negative.
|
||||
|
||||
In code, they are written just like numbers:
|
||||
Same as php int
|
||||
|
||||
```thp
|
||||
val age = 33
|
||||
val children = 0
|
||||
val money = -15000
|
||||
```
|
||||
|
||||
You can use underscores to help you differentiate thousands, millions, etc.
|
||||
However, there cannot be spaces in between
|
||||
|
||||
```thp
|
||||
val studentDebt = 3_500_000_000_000 // Valid
|
||||
val invalid = 3 500 000 000 000 // Invalid, will throw an error
|
||||
```
|
||||
|
||||
The common operations can be done as in math:
|
||||
|
||||
```thp
|
||||
val result1 = 10 + 20
|
||||
val result2 = 1779 * 2 - (55 / 5)
|
||||
Int age = 32
|
||||
Int red = 0xff0000
|
||||
Int char_code = 0b01000110
|
||||
```
|
||||
|
||||
|
||||
### Float
|
||||
## Float
|
||||
|
||||
Float is an abbreviation for "floating point numbers". In simplified terms, these are numbers
|
||||
**with** a fractional component.
|
||||
|
||||
They are written with a dot `.` to separate the whole part and the fraction.
|
||||
|
||||
```thp
|
||||
val pi = 3.141592
|
||||
val epsilon = 2.775557
|
||||
```
|
||||
|
||||
Underscore can also be used:
|
||||
|
||||
```thp
|
||||
val reallyLongNumber = 23_870_000.443_879
|
||||
```
|
||||
|
||||
Common operations can be performed the same way:
|
||||
|
||||
```thp
|
||||
val value1 = 552.23 - 32
|
||||
val value2 = 3.2 * (-0.22 + 23.334) / 0.5
|
||||
// etc.
|
||||
```
|
||||
|
||||
### String
|
||||
|
||||
A string of letters (technically, characters). Strings are used to represent text,
|
||||
and are wrapped in quotation marks.
|
||||
|
||||
```thp
|
||||
val name = "John"
|
||||
val lastName = "Doe"
|
||||
|
||||
val greeting = "Hello"
|
||||
```
|
||||
|
||||
#### Concatenation
|
||||
|
||||
Strings cannot be added, substracted, multiplied, divided.
|
||||
They have another operation, called "concatenation".
|
||||
|
||||
Concatenation "joins" two strings, for example, the concatenation of
|
||||
`"human"` and `"kind"` is `"humankind"`.
|
||||
|
||||
As it is a common operation, string concatenation reuses the operation
|
||||
for addition `+`.
|
||||
|
||||
```thp
|
||||
val string = "human" + "kind"
|
||||
```
|
||||
|
||||
|
||||
### Boolean
|
||||
|
||||
A boolean represents something that can only be in one of two states.
|
||||
|
||||
Booleans are useful in conditionals, which will be explained later.
|
||||
Same as php float
|
||||
|
||||
|
||||
```thp
|
||||
val condition = true
|
||||
val isSunny = false
|
||||
|
||||
if isSunny {
|
||||
doSomething()
|
||||
}
|
||||
Float pi = 3.141592
|
||||
```
|
||||
|
||||
|
||||
## String
|
||||
|
||||
Same as php string
|
||||
|
||||
```thp
|
||||
String name = "Rose"
|
||||
```
|
||||
|
||||
|
||||
## Bool
|
||||
|
||||
Same as php bool
|
||||
|
||||
```thp
|
||||
Bool is_true = true
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,60 +1,9 @@
|
||||
# Hello, world!
|
||||
|
||||
This pages shows you how to write and run your first THP script.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You will need to have PHP and THP installed. If you haven't already, see the
|
||||
install page.
|
||||
|
||||
## Writing the program
|
||||
|
||||
Create a new file called `hello.thp`, and inside write the following (you can
|
||||
copy and paste):
|
||||
Create a file named `hello.thp` with the contents:
|
||||
|
||||
```thp
|
||||
print("Hello, world!")
|
||||
```
|
||||
|
||||
Then, save the code.
|
||||
|
||||
## Running the program
|
||||
|
||||
Open a terminal in the folder where you created the file `hello.thp`.
|
||||
Then write the following command and press enter:
|
||||
|
||||
```sh
|
||||
thp hello.thp
|
||||
```
|
||||
|
||||
This will run the program, and produce the following result:
|
||||
|
||||
```sh
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Congratulations! You just wrote your first THP program!
|
||||
|
||||
## Explaining the program
|
||||
|
||||
Now let's understand the code.
|
||||
|
||||
```thp
|
||||
print("Hello, world!")
|
||||
```
|
||||
|
||||
There are 2 essential components:
|
||||
|
||||
- `print` - print is a "function", it takes some value and performs some action with it.
|
||||
In this case, it takes a text and displays it in the terminal.
|
||||
- `"Hello, world!"` - Is the text that the function `print` takes, and displays in
|
||||
the terminal. Note that it is enclosed in quotation marks.
|
||||
|
||||
## What to do next
|
||||
|
||||
You can now experiment with the program you wrote. What happens if you change the text?
|
||||
What if you don't put quotation marks? And what are the parenthesis for?
|
||||
|
||||
To continue learning about THP, continue to the next page, where you'll learn
|
||||
about "datatypes".
|
||||
|
||||
Then run `thp hello.thp`
|
||||
|
@ -1,64 +0,0 @@
|
||||
# Input & Output
|
||||
|
||||
At the end of the day, a program takes some input,
|
||||
and transform it to some output. We will explore how to
|
||||
receive data, and also present it.
|
||||
|
||||
## Output
|
||||
|
||||
There are many ways to show the result of our programs.
|
||||
One of them is called `standard output`, which in simplified
|
||||
terms, is the terminal from where we run our program.
|
||||
|
||||
### `print`
|
||||
|
||||
Create an empty file, and name it `hello.php`. We will create
|
||||
a program that shows a result to our screen.
|
||||
|
||||
Inside `hello.php` write the following code:
|
||||
|
||||
```thp
|
||||
print("Hello")
|
||||
```
|
||||
|
||||
Then, open a terminal and run the program with the `thp` command.
|
||||
After you press ENTER, you will see in the terminal the text "Hello".
|
||||
|
||||
|
||||
```sh
|
||||
$ thp hello.thp # Copy this command and run it
|
||||
Hello # This is the output of our program
|
||||
```
|
||||
|
||||
The thp function `print` allows us to display something in the terminal.
|
||||
|
||||
If you change the `hello.php` file, and run it, you'll see how it changes.
|
||||
|
||||
```thp
|
||||
print(322)
|
||||
```
|
||||
```sh
|
||||
$ thp hello.php
|
||||
322
|
||||
```
|
||||
|
||||
Or, if you copy `print` multiple times, each will show something in the screen.
|
||||
|
||||
```thp
|
||||
print("Hello")
|
||||
print("This is an example")
|
||||
print("of having many prints")
|
||||
```
|
||||
```sh
|
||||
$ thp hello.php
|
||||
Hello
|
||||
This is an example
|
||||
of having many prints
|
||||
```
|
||||
|
||||
### Using `print` in a larger program
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
# The compiler
|
||||
|
||||
The compiler is the program that takes your THP code and converts it
|
||||
into something that the computer can run (in this case, PHP code).
|
||||
|
||||
|
||||
|
||||
The compiler reads your code and tries to understand it.
|
||||
When it can't understand some part, it will ask you to clarify what
|
||||
you meant, with an error.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Compile time vs runtime
|
||||
|
||||
Compile time is when you build your program.
|
||||
|
||||
Runtime is when you run your program.
|
||||
|
||||
To make an analogy with cars, compile time would be the factory,
|
||||
while runtime would be using the finished car.
|
||||
|
||||
|
||||
|
||||
The compiler is very strict. If it finds any errors during compile time
|
||||
it will refuse to build the program.
|
||||
|
||||
|
||||
### Compile time errors
|
||||
|
||||
Compile time errors are errors that happen while the compiler is
|
||||
building your program. In the car analogy, a compile error would happen
|
||||
if there's an error in the "blueprint"
|
||||
|
||||
|
||||
### Runtime errors
|
||||
|
||||
These are errors that happen to the built program, or in this case,
|
||||
the finished car. It would be like the car blowing up while on the highway.
|
||||
|
||||
To minimize the amount of runtime errors the compiler tries to catch them all
|
||||
during compile time. It's better if it fails in the factory than in the
|
||||
real world.
|
||||
|
||||
|
||||
## The compiler and datatypes
|
||||
|
||||
The first measure the compiler takes is to check that all the datatypes
|
||||
match. If an operation requires a number, you can't just give it a string.
|
||||
|
||||
|
||||
|
||||
For example, if we wanted to add a number to a string, we would get an
|
||||
error:
|
||||
|
||||
```thp
|
||||
50 + "hello" // Error: The `+` operator expects two Numbers,
|
||||
// but an String was found.
|
||||
```
|
||||
|
||||
This way, we can assure that many errors are avoided (since it doesn't
|
||||
really make sense to add a number to a text).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,138 +1,55 @@
|
||||
# Variables
|
||||
|
||||
Variables allows us to store values under a name, so that we can use them
|
||||
later.
|
||||
thp distinguishes between mutable and immutable variables.
|
||||
|
||||
For example, in a program we could have the name of our user, and use it
|
||||
multiple times:
|
||||
## Mutable variables
|
||||
|
||||
Defined with `var`, followed by a variable name and a value.
|
||||
|
||||
```thp
|
||||
print("Hello, where's Joe?")
|
||||
print("How old is Joe?")
|
||||
print("Do you know if Joe has kids?")
|
||||
var name = "John"
|
||||
var age = 32
|
||||
```
|
||||
|
||||
We are using the same value `Joe` many times. Each time we use it we have
|
||||
to type `Joe`. But what happens if we needed to use a different name?
|
||||
We'd have to change the name everywhere in our code!
|
||||
### Datatype annotation
|
||||
|
||||
Written after the `var` keyword but before the variable name.
|
||||
|
||||
```thp
|
||||
print("Hello, where's Jane?")
|
||||
print("How old is Jane?")
|
||||
print("Do you know if Jane has kids?")
|
||||
var String name = "John"
|
||||
var Int age = 32
|
||||
```
|
||||
|
||||
## Variables to the rescue
|
||||
When annotating a mutable variable the keyword `var` is _required_.
|
||||
|
||||
With a variable we can store values so we can use them later, or use them
|
||||
in multiple times.
|
||||
|
||||
In the previous code, we can use a variable to store the person's name,
|
||||
and then use it everywhere.
|
||||
## Immutable variables
|
||||
|
||||
Defined with `val`, followed by a variable name and a value.
|
||||
|
||||
```thp
|
||||
// This is the variable
|
||||
val person = "John"
|
||||
|
||||
print("Hello, where's {person}?")
|
||||
print("How old is {person}?")
|
||||
print("Do you know if Joe has {person}?")
|
||||
val surname = "Doe"
|
||||
val year_of_birth = 1984
|
||||
```
|
||||
|
||||
Now, instead of writing `"John"` every time, we write the name of the
|
||||
variable instead.
|
||||
### Datatype annotation
|
||||
|
||||
If we wanted to change the person's name to "Jane", we just need to change
|
||||
it in one place: the variable
|
||||
Same as mutable variables
|
||||
|
||||
```thp
|
||||
// We change this
|
||||
val person = "Jane"
|
||||
|
||||
// And all these lines will use the new value
|
||||
print("Hello, where's {person}?")
|
||||
print("How old is {person}?")
|
||||
print("Do you know if Joe has {person}?")
|
||||
val String surname = "Doe"
|
||||
val Int year_of_birth = 1984
|
||||
```
|
||||
|
||||
## Variable rules
|
||||
|
||||
To use a variable we do the following:
|
||||
|
||||
- Write the special word `val`
|
||||
- Write the name of our variable
|
||||
- Write the equal sign `=`
|
||||
- Write the value of our variable
|
||||
When annotating an immutable variable the `val` keyword is optional
|
||||
|
||||
```thp
|
||||
val person = "Jane"
|
||||
/* --- ------ - ------
|
||||
| | | +- The value of our variable
|
||||
| | +----- The equal sign
|
||||
| +---------- The name of our variable
|
||||
+--------------- The special word (keyword) val
|
||||
*/
|
||||
// Equivalent to the previous code
|
||||
String surname = "Doe"
|
||||
Int year_of_birth = 1984
|
||||
```
|
||||
|
||||
The value can be anything: ints, floats, string, bools, even other variables and operations!
|
||||
|
||||
```thp
|
||||
val variable_1 = 322
|
||||
val variable_2 = 123.456
|
||||
val variable_3 = "a text"
|
||||
val variable_4 = false
|
||||
val variable_5 = variable_1 + variable 2
|
||||
```
|
||||
|
||||
## Variable name rules
|
||||
|
||||
- Starts with a lowercase letter (a-z) or underscore (`_`)
|
||||
- Then can have any letter (a-zA-Z), underscore (`_`) or number (0-9)
|
||||
- Cannot have spaces
|
||||
- Cannot have the same name as a keyword (for example, the `val` keyword)
|
||||
|
||||
|
||||
Some examples of valid variable names:
|
||||
|
||||
```thp
|
||||
val name = ...
|
||||
val age = ...
|
||||
val my_name = ...
|
||||
val many_words_joined_by_underscores = ...
|
||||
val person_2 = ...
|
||||
val person_3 = ...
|
||||
```
|
||||
|
||||
Some invalid variables and why they are invalid:
|
||||
|
||||
```thp
|
||||
val 1name = ... // Invalid: starts with a number
|
||||
val 123_person = ... // Invalid: starts with a number
|
||||
val val = ... // Invalid: same name as a keyword (val)
|
||||
val Person = ... // Invalid: starts with an uppercase letter
|
||||
val person name = ... // Invalid: contains whitespace
|
||||
val +@name = ... // Invalid: contains non-letters (+@)
|
||||
val name🫠 = ... // Invalid: contains emoji (🫠)
|
||||
```
|
||||
|
||||
|
||||
## Variable reassignment
|
||||
|
||||
When you create a new variable with the same name of an old variable,
|
||||
the old is "replaced" with the new one.
|
||||
|
||||
```thp
|
||||
val person_name = "John"
|
||||
print(person_name) // Will print "John"
|
||||
|
||||
val person_name = "Jane"
|
||||
print(person_name) // Will print "Jane"
|
||||
```
|
||||
|
||||
This will have some implications on the future, but for now you should
|
||||
now that you will always use the value of the last variable you define.
|
||||
|
||||
|
||||
This means that if a variable has only a datatype, it is immutable.
|
||||
|
||||
|
||||
|
||||
|
94
md/learn/classes/definition.md
Normal file
94
md/learn/classes/definition.md
Normal file
@ -0,0 +1,94 @@
|
||||
# Classes
|
||||
|
||||
Basically kotlin syntax.
|
||||
|
||||
Methods have to have a first parameter `$`.
|
||||
|
||||
|
||||
## Create a new instance of a class
|
||||
|
||||
`new` not required, in fact, forbidden.
|
||||
|
||||
```thp
|
||||
val dog = Dog()
|
||||
```
|
||||
|
||||
## Simple class
|
||||
|
||||
Why'd you do this tho?
|
||||
|
||||
```thp
|
||||
class SimpleClass
|
||||
|
||||
val instance = SimpleClass()
|
||||
```
|
||||
|
||||
## Properties & methods
|
||||
|
||||
```thp
|
||||
class SimpleClass
|
||||
{
|
||||
// Properties are private by default
|
||||
var String? name;
|
||||
|
||||
// Made public with `public`
|
||||
public var String? surname;
|
||||
|
||||
// Methods are private by default
|
||||
fun display_name($)
|
||||
{
|
||||
// `$` is used instead of $this
|
||||
print($name)
|
||||
}
|
||||
|
||||
public fun get_name($) -> String?
|
||||
{
|
||||
$name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Static members
|
||||
|
||||
no
|
||||
|
||||
|
||||
## Constructor
|
||||
|
||||
Kotlin style
|
||||
|
||||
|
||||
```thp
|
||||
class Cat(val String name)
|
||||
{
|
||||
public fun get_name($) -> String
|
||||
{
|
||||
$name
|
||||
}
|
||||
}
|
||||
|
||||
val michifu = Cat("Michifu")
|
||||
print(michifu.get_name())
|
||||
```
|
||||
|
||||
## Inheritance
|
||||
|
||||
Kotlin style
|
||||
|
||||
```thp
|
||||
class Animal(val String name)
|
||||
{
|
||||
public fun say_name($)
|
||||
{
|
||||
print($name)
|
||||
}
|
||||
}
|
||||
|
||||
class Cat(String name, Int lives) -> Animal(name)
|
||||
|
||||
Cat("Michi", 9).say_name()
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
48
md/learn/classes/static.md
Normal file
48
md/learn/classes/static.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Static in classes
|
||||
|
||||
|
||||
## Class constants
|
||||
|
||||
```thp
|
||||
static Cat {
|
||||
const CONSTANT = "constant value"
|
||||
}
|
||||
|
||||
print(Cat::CONSTANT)
|
||||
```
|
||||
|
||||
|
||||
## Static methods
|
||||
|
||||
aka. plain, old functions
|
||||
|
||||
|
||||
```thp
|
||||
static Cat {
|
||||
fun static_method() -> Int {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
Cat::static_method()
|
||||
```
|
||||
|
||||
|
||||
## Static properties
|
||||
|
||||
aka. global variables
|
||||
|
||||
|
||||
```thp
|
||||
static Cat {
|
||||
public var access_count = 0
|
||||
}
|
||||
|
||||
print(Cat::access_count) // 0
|
||||
Cat::access_count += 1
|
||||
print(Cat::access_count) // 1
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
35
md/learn/collections/arrays.md
Normal file
35
md/learn/collections/arrays.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Arrays
|
||||
|
||||
No destructuring (for now?). There's no `[]` syntax
|
||||
for constructing arrays
|
||||
|
||||
## Usage
|
||||
|
||||
```thp
|
||||
val fruits = Array("apple", "banana", "cherry")
|
||||
val apple = fruits.[0]
|
||||
|
||||
print(apple)
|
||||
|
||||
|
||||
var numbers = Array(0, 1, 2, 3)
|
||||
|
||||
// Note the dot
|
||||
numbers.[3] = 5
|
||||
|
||||
print(numbers.[3]) // 5
|
||||
```
|
||||
|
||||
|
||||
## Type signature
|
||||
|
||||
|
||||
```thp
|
||||
Array[String]
|
||||
Array[Int]
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
43
md/learn/collections/maps.md
Normal file
43
md/learn/collections/maps.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Maps
|
||||
|
||||
Also known as Associative Arrays
|
||||
|
||||
|
||||
## Usage without a declaration
|
||||
|
||||
```thp
|
||||
var person = Obj {
|
||||
name: "John",
|
||||
surname: "Doe",
|
||||
age: 33,
|
||||
}
|
||||
|
||||
|
||||
print("Hello {person.name}")
|
||||
|
||||
person.age += 1
|
||||
|
||||
print("You just turned {person.age}")
|
||||
```
|
||||
|
||||
|
||||
## Usage with a declaration
|
||||
|
||||
```thp
|
||||
obj Person = {
|
||||
String name,
|
||||
String surname,
|
||||
Int age,
|
||||
}
|
||||
|
||||
|
||||
val john_doe = Person {
|
||||
name: "John",
|
||||
surname: "Doe",
|
||||
age: 33,
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
11
md/learn/collections/sets.md
Normal file
11
md/learn/collections/sets.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Sets
|
||||
|
||||
|
||||
```thp
|
||||
// Set[Int]
|
||||
val ages = Set(30, 31, 33, 35)
|
||||
|
||||
for age in ages {
|
||||
print("{age}")
|
||||
}
|
||||
```
|
22
md/learn/collections/tuples.md
Normal file
22
md/learn/collections/tuples.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Tuples
|
||||
|
||||
Uses `#()` just to avoid confusion with function
|
||||
calls (`()`).
|
||||
|
||||
## Definition
|
||||
|
||||
```thp
|
||||
val person = #("John", "Doe", 32)
|
||||
|
||||
val #(name, surname, age) = person
|
||||
```
|
||||
|
||||
|
||||
## Signature
|
||||
|
||||
```thp
|
||||
#(String, String, Int)
|
||||
```
|
||||
|
||||
|
||||
|
@ -1,3 +1,57 @@
|
||||
# Conditionals
|
||||
|
||||
- Only `Bool` are accepted. No truthy/falsy.
|
||||
- Conditionals are expressions.
|
||||
- Braces are required
|
||||
- Paretheses for the condition are not required.
|
||||
- There's no ternary operator
|
||||
|
||||
|
||||
```thp
|
||||
if condition
|
||||
{
|
||||
// code
|
||||
}
|
||||
else if condition2
|
||||
{
|
||||
// more code
|
||||
}
|
||||
else
|
||||
{
|
||||
// even more code
|
||||
}
|
||||
|
||||
|
||||
val result = if condition { value1 } else { value2 }
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Check for datatypes
|
||||
|
||||
```thp
|
||||
if variable is Datatype
|
||||
{
|
||||
// code using variable
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## If variable is of enum
|
||||
|
||||
```thp
|
||||
val user_id = POST::get("user_id")
|
||||
|
||||
if Some(user_id) = user_id
|
||||
{
|
||||
print("user_id exists: {user_id}")
|
||||
}
|
||||
|
||||
if Some(user_id) = user_id && user_id > 0
|
||||
{
|
||||
print("user_id is greater than 0: {user_id}")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
82
md/learn/flow-control/loops.md
Normal file
82
md/learn/flow-control/loops.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Loops
|
||||
|
||||
## For loop
|
||||
|
||||
Braces are required.
|
||||
|
||||
```thp
|
||||
val numbers = Array(0, 1, 2, 3)
|
||||
|
||||
for number in numbers
|
||||
{
|
||||
print(number)
|
||||
}
|
||||
|
||||
for #(index, number) in numbers.entries()
|
||||
{
|
||||
print("{index} => {number}")
|
||||
}
|
||||
```
|
||||
|
||||
```thp
|
||||
val dict = Obj {
|
||||
"apple": 10,
|
||||
"banana": 7,
|
||||
"cherries": 3,
|
||||
}
|
||||
|
||||
for #(key, value) in dict
|
||||
{
|
||||
print("{key} => {value}")
|
||||
}
|
||||
```
|
||||
|
||||
```thp
|
||||
for value in collection
|
||||
{
|
||||
if condition
|
||||
{
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## While loop
|
||||
|
||||
```thp
|
||||
val colors = Array("red", "green", "blue")
|
||||
var index = 0
|
||||
|
||||
while index < colors.size()
|
||||
{
|
||||
print("{colors.[index]}")
|
||||
index += 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Infinite loop
|
||||
|
||||
Basically Rust's loop.
|
||||
|
||||
```thp
|
||||
loop
|
||||
{
|
||||
print("looping")
|
||||
|
||||
if condition
|
||||
{
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
# Match
|
||||
|
||||
## Most likely syntax
|
||||
|
||||
```thp
|
||||
val user_id = POST::get("user_id")
|
||||
|
||||
|
||||
match user_id
|
||||
| Some(id){ print("user_id exists: {id}") }
|
||||
| None { print("user_id doesn't exist") }
|
||||
|
||||
match user_id
|
||||
| Some(id)
|
||||
{
|
||||
print("user_id exists: {id}")
|
||||
}
|
||||
| None
|
||||
{
|
||||
print("user_id doesn't exist")
|
||||
}
|
||||
|
||||
|
||||
match user_id
|
||||
| Some(id) if id > 0
|
||||
{
|
||||
print("user_id exists: {id}")
|
||||
}
|
||||
| _
|
||||
{
|
||||
print("user_id has other values ")
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Alternative syntax?
|
||||
|
||||
```thp
|
||||
// Alternative syntax?
|
||||
|
||||
match user_id {
|
||||
Some(id) { print("user_id exists: {id}") }
|
||||
None { print("user_id doesn't exist") }
|
||||
}
|
||||
|
||||
match user_id {
|
||||
Some(id) {
|
||||
print("user_id exists: {id}")
|
||||
}
|
||||
None {
|
||||
print("user_id doesn't exist")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
70
md/learn/functions/declaration.md
Normal file
70
md/learn/functions/declaration.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Declaration
|
||||
|
||||
|
||||
## No parameters, no return
|
||||
|
||||
```thp
|
||||
fun say_hello()
|
||||
{
|
||||
print("Hello")
|
||||
}
|
||||
|
||||
say_hello()
|
||||
```
|
||||
|
||||
|
||||
## With return type
|
||||
|
||||
```thp
|
||||
fun get_random_number() -> Int
|
||||
{
|
||||
Random::get(0, 35_222)
|
||||
}
|
||||
|
||||
val number = get_random_number()
|
||||
```
|
||||
|
||||
## With parameters and return type
|
||||
|
||||
```thp
|
||||
fun get_secure_random_number(Int min, Int max) -> Int
|
||||
{
|
||||
Random::get_secure(min, max)
|
||||
}
|
||||
|
||||
val number = get_secure_random_number(0, 65535)
|
||||
```
|
||||
|
||||
|
||||
## Generic types
|
||||
|
||||
```thp
|
||||
fun get_first_item[T](Array[T] array) -> T
|
||||
{
|
||||
array.[0]
|
||||
}
|
||||
|
||||
val first = get_first_item[Int](numbers)
|
||||
// The type annotation is optional if the compiler can infer the type
|
||||
|
||||
val first = get_first_item(numbers)
|
||||
```
|
||||
|
||||
|
||||
## Signature
|
||||
|
||||
|
||||
```thp
|
||||
() -> ()
|
||||
() -> Int
|
||||
(Int, Int) -> Int
|
||||
[T](Array[T]) -> T
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
28
md/learn/functions/higher-order.md
Normal file
28
md/learn/functions/higher-order.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Higher Order functions
|
||||
|
||||
|
||||
## Function as parameter
|
||||
|
||||
```thp
|
||||
fun map[A, B](Array[A] input, (A) -> B function) -> Array[B]
|
||||
{
|
||||
// implementation
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Function as return
|
||||
|
||||
```thp
|
||||
fun generate_generator() -> () -> Int
|
||||
{
|
||||
// code...
|
||||
}
|
||||
|
||||
|
||||
val generator = generate_generator() // A function
|
||||
val value = generate_generator()() // An Int
|
||||
```
|
||||
|
||||
|
||||
|
70
md/learn/functions/lambdas.md
Normal file
70
md/learn/functions/lambdas.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Lambdas / Anonymous functions
|
||||
|
||||
|
||||
## Anonymous function
|
||||
|
||||
```thp
|
||||
fun(Int x, Int y) -> Int {
|
||||
x + y
|
||||
}
|
||||
|
||||
|
||||
numbers.map(fun(x) {
|
||||
x * 2
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Closure types
|
||||
|
||||
By default closures **always** capture variables as **references**.
|
||||
|
||||
|
||||
```thp
|
||||
var x = 20
|
||||
|
||||
val f = fun() {
|
||||
print(x)
|
||||
}
|
||||
|
||||
f() // 20
|
||||
|
||||
x = 30
|
||||
f() // 30
|
||||
```
|
||||
|
||||
|
||||
You can force a closure to capture variables by value.
|
||||
|
||||
```thp
|
||||
fun(parameters) clone(variables) {
|
||||
// code
|
||||
}
|
||||
```
|
||||
|
||||
```thp
|
||||
var x = 20
|
||||
|
||||
val f = fun() clone(x) {
|
||||
print(x)
|
||||
}
|
||||
|
||||
f() // 20
|
||||
|
||||
x = 30
|
||||
f() // 20
|
||||
```
|
||||
|
||||
|
||||
## Lambdas
|
||||
|
||||
|
||||
```thp
|
||||
numbers.map {
|
||||
it * 2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
@ -24,21 +24,21 @@ fun count(Array[Int] numbers) -> Int {
|
||||
## Mutable reference
|
||||
|
||||
```thp
|
||||
fun add_25(&Array[Int] numbers) {
|
||||
fun push_25(&Array[Int] numbers) {
|
||||
numbers.push(25) // Ok, will also mutate the original array
|
||||
}
|
||||
```
|
||||
|
||||
Placing a `&` before the type makes the parameter a mutable
|
||||
reference. Mutable methods can be used, and the original
|
||||
data **will** be mutated.
|
||||
data **can** be mutated.
|
||||
|
||||
The callee *must* also use `&`.
|
||||
The caller *must* also use `&`.
|
||||
|
||||
```thp
|
||||
val numbers = Array(1, 2, 3, 4)
|
||||
val numbers = Array(0, 1, 2, 3)
|
||||
|
||||
add_25(&numbers) // Pass `numbers` as reference.
|
||||
push_25(&numbers) // Pass `numbers` as reference.
|
||||
|
||||
print(numbers(4)) // `Some(25)`
|
||||
```
|
||||
@ -54,13 +54,13 @@ fun add_25(clone Array[Int] numbers) {
|
||||
```
|
||||
|
||||
Using the `clone` keyword before the type creates a mutable copy
|
||||
of the parameter. The original data will **not** be mutated.
|
||||
of the parameter (CoW). The original data will **not** be mutated.
|
||||
|
||||
|
||||
```thp
|
||||
val numbers = Array(1, 2, 3, 4)
|
||||
|
||||
add_25(&numbers) // Pass `numbers` as reference.
|
||||
add_25(numbers) // Pass `numbers` as clone.
|
||||
|
||||
print(numbers(4)) // None
|
||||
```
|
||||
|
@ -1,3 +1,6 @@
|
||||
![Accurate visual description of THP](/img/desc_thp.jpg)
|
||||
|
||||
|
||||
# Welcome
|
||||
|
||||
Welcome to the documentation of the THP programming languague.
|
||||
@ -7,7 +10,7 @@ THP is a new programming language that compiles to PHP.
|
||||
<br>
|
||||
|
||||
This page discusses some of the design decitions of the language,
|
||||
if you want to install THP go to the installation guide](/installation-guide)
|
||||
if you want to install THP go to the [installation guide](/installation-guide)
|
||||
|
||||
If you want to learn the language, go to the learn section.
|
||||
|
||||
|
@ -11,14 +11,10 @@ children:
|
||||
children:
|
||||
- path: hello-world
|
||||
name: Hello, world!
|
||||
- path: datatypes
|
||||
name: Datatypes
|
||||
- path: the-compiler
|
||||
name: The compiler
|
||||
- name: Variables
|
||||
path: variables
|
||||
- path: io
|
||||
name: Input & Output
|
||||
- path: datatypes
|
||||
name: Datatypes
|
||||
- path: comments
|
||||
name: Comments
|
||||
- name: Flow control
|
||||
@ -26,3 +22,41 @@ children:
|
||||
children:
|
||||
- name: Conditionals
|
||||
path: conditionals
|
||||
- name: Loops
|
||||
path: loops
|
||||
- name: Match
|
||||
path: match
|
||||
- name: Collections
|
||||
path: collections
|
||||
children:
|
||||
- name: Tuples
|
||||
path: tuples
|
||||
- name: Arrays
|
||||
path: arrays
|
||||
- name: Maps
|
||||
path: maps
|
||||
- name: Sets
|
||||
path: sets
|
||||
- name: Functions
|
||||
path: functions
|
||||
children:
|
||||
- name: Declaration
|
||||
path: declaration
|
||||
- name: Parameter references
|
||||
path: parameters
|
||||
- name: Higher-order functions
|
||||
path: higher-order
|
||||
- name: Lambdas
|
||||
path: lambdas
|
||||
- name: ADTs
|
||||
path: adts
|
||||
children:
|
||||
- name: Union types
|
||||
path: union-types
|
||||
- name: Classes
|
||||
path: classes
|
||||
children:
|
||||
- name: Definition
|
||||
path: definition
|
||||
- name: Static
|
||||
path: static
|
||||
|
BIN
static/img/desc_thp.jpg
Normal file
BIN
static/img/desc_thp.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
@ -16,12 +16,23 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Josefin+Sans:ital,wght@0,400;1,700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-c-bg text-c-text">
|
||||
<nav class="sticky top-0 h-16 border-b border-gray-400 bg-[rgba(18,18,18,0.5)] backdrop-blur-md z-20">
|
||||
<div class="max-w-[70rem] mx-auto h-full w-full flex items-center">
|
||||
<button class="font-display font-bold italic text-4xl">
|
||||
<span
|
||||
class="text-[#F5A9B8]"
|
||||
>t</span><span>h</span><span class="text-[#5BCEFA]">p</span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div
|
||||
class="max-w-[70rem] mx-auto py-28 grid grid-cols-2 gap-4"
|
||||
class="max-w-[70rem] mx-auto py-16 grid grid-cols-2 gap-4"
|
||||
>
|
||||
<div>
|
||||
<h1 class="font-display font-bold italic text-[6rem] leading-tight">
|
||||
<h1
|
||||
class="font-display font-bold italic text-[6rem] leading-tight"
|
||||
>
|
||||
Typed
|
||||
<br>
|
||||
Hypertext
|
||||
@ -33,32 +44,34 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div
|
||||
class="bg-[var(--code-theme-bg-color)] p-8 rounded-lg"
|
||||
class="bg-[var(--code-theme-bg-color)] p-8 rounded-lg relative"
|
||||
>
|
||||
<span class="absolute inline-block h-[40rem] w-[40rem] -z-10 top-1/2 left-1/2 rounded-full
|
||||
transform -translate-x-1/2 -translate-y-1/2"
|
||||
style="background-image: conic-gradient(from 180deg at 50% 50%,#5BCEFA 0deg,#a853ba 180deg,#F5A9B8 1turn);
|
||||
filter: blur(75px); opacity: 0.75;"
|
||||
>
|
||||
</span>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg>
|
||||
<br>
|
||||
<pre
|
||||
class="rounded-md bg-c-bg language-misti"
|
||||
style="padding: 0 !important;"
|
||||
><span class="token keyword">use</span> <span class="token class-name">Globals</span>::<span class="token class-name">POST</span>
|
||||
<span class="token keyword">use</span> <span class="token class-name">JSON</span>
|
||||
|
||||
<span class="token keyword">val</span> person_id = <span class="token class-name">POST</span>::get(<span class="token string">"person_id"</span>) ?: <span class="token keyword">die</span>
|
||||
|
||||
<span class="token keyword">match</span> <span class="token class-name">Person</span>::find_by_id(person_id) {
|
||||
<span class="token class-name">Ok</span>(person) => {
|
||||
<span class="token class-name">JSON</span>::encode(person)
|
||||
}
|
||||
<span class="token class-name">Err</span>(e) => {
|
||||
<span class="token class-name">JSON</span>::encode(Obj {<span class="token string">"error"</span>: e})
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<pre style="padding: 0 !important;">
|
||||
<code class="language-thp">
|
||||
val person_id = POST::get("person_id") ?: die
|
||||
|
||||
match Person::find_by_id(person_id)
|
||||
| Ok(person)
|
||||
{
|
||||
JSON::encode(person)
|
||||
}
|
||||
| Err(e)
|
||||
{
|
||||
JSON::encode(Obj {"error": e})
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -78,5 +91,8 @@
|
||||
Install
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<script src="/js/prism.min.js"></script>
|
||||
<script src="/js/prism.thp.js"></script>
|
||||
</body>
|
||||
</html>
|
4
static/js/prism.min.js
vendored
Normal file
4
static/js/prism.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
25
static/js/prism.thp.js
Normal file
25
static/js/prism.thp.js
Normal file
@ -0,0 +1,25 @@
|
||||
Prism.languages.thp = {
|
||||
"comment": [
|
||||
{
|
||||
pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
|
||||
lookbehind: true,
|
||||
greedy: true,
|
||||
},
|
||||
{
|
||||
pattern: /(^|[^\\:])\/\/.*/,
|
||||
lookbehind: true,
|
||||
greedy: true,
|
||||
},
|
||||
],
|
||||
"string": {
|
||||
pattern: /(["])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
|
||||
greedy: true,
|
||||
},
|
||||
"keyword": /\b(?:break|catch|continue|do|else|elif|finally|for|fun|if|in|fn|nil|return|throw|try|while|val|var|type|match|with|of|abstract|class|interface|private|public|override|open)\b/,
|
||||
"number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
|
||||
"operator": /[<>]=?|[!=]=?=?|--?|\$|\+\+?|&&?|\|\|?|[?*/~^%]/,
|
||||
"punctuation": /[{}[\];(),.]/,
|
||||
"boolean": /\b(?:false|true)\b/,
|
||||
"class-name": /\b[A-Z][a-zA-Z_0-9]+\b/,
|
||||
"variable": /\b[a-z_0-9][a-zA-Z_0-9]+:/,
|
||||
};
|
Loading…
Reference in New Issue
Block a user