refactor: move learn files to versioned folder
This commit is contained in:
parent
67ff5203a6
commit
83c382d361
@ -7,10 +7,6 @@ const basePath: string = Astro.props.basePath;
|
|||||||
const entryPath = is_index_file(entry.path)? "": entry.path;
|
const entryPath = is_index_file(entry.path)? "": entry.path;
|
||||||
|
|
||||||
const entryUrl = basePath + entryPath + (entryPath.endsWith("/")? "" : "/");
|
const entryUrl = basePath + entryPath + (entryPath.endsWith("/")? "" : "/");
|
||||||
console.table({
|
|
||||||
basePath,
|
|
||||||
entryPath,
|
|
||||||
})
|
|
||||||
|
|
||||||
function is_index_file(p) {
|
function is_index_file(p) {
|
||||||
return p.endsWith("index")
|
return p.endsWith("index")
|
||||||
@ -35,7 +31,7 @@ function is_index_file(p) {
|
|||||||
entry.children && (
|
entry.children && (
|
||||||
<>
|
<>
|
||||||
<div class="mt-6 px-3 py-1 uppercase font-display text-c-text-2 font-medium">
|
<div class="mt-6 px-3 py-1 uppercase font-display text-c-text-2 font-medium">
|
||||||
{entry.title}
|
{entry.title.replaceAll("-", " ")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="my-1">
|
<ul class="my-1">
|
||||||
|
@ -21,6 +21,7 @@ export interface AstroFile {
|
|||||||
export interface Frontmatter {
|
export interface Frontmatter {
|
||||||
layout: string
|
layout: string
|
||||||
title: string
|
title: string
|
||||||
|
order: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -56,7 +57,8 @@ const second_level: Record<string, Array<AstroFile>> = {
|
|||||||
for (const post of posts_2) {
|
for (const post of posts_2) {
|
||||||
const fragments = post.path.split("/");
|
const fragments = post.path.split("/");
|
||||||
if (fragments.length === 3) {
|
if (fragments.length === 3) {
|
||||||
const folder_name = fragments[1];
|
const folder_name = fragments[1]!;
|
||||||
|
|
||||||
// create if not exists
|
// create if not exists
|
||||||
if (second_level[folder_name] === undefined) {
|
if (second_level[folder_name] === undefined) {
|
||||||
second_level[folder_name] = [];
|
second_level[folder_name] = [];
|
||||||
@ -65,21 +67,21 @@ for (const post of posts_2) {
|
|||||||
}
|
}
|
||||||
else if (fragments.length === 2) {
|
else if (fragments.length === 2) {
|
||||||
// add to root folder
|
// add to root folder
|
||||||
second_level["_"].push(post);
|
second_level["_"]!.push(post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform to the layout that the sidebar expects
|
// transform to the layout that the sidebar expects
|
||||||
|
|
||||||
const entries = [];
|
const entries: Array<any> = [];
|
||||||
for (const levels_key in second_level) {
|
for (const levels_key in second_level) {
|
||||||
if (levels_key === "_") {
|
if (levels_key === "_") {
|
||||||
// top level
|
// top level
|
||||||
const posts = second_level[levels_key];
|
const posts = second_level[levels_key]!;
|
||||||
entries.push(...posts)
|
entries.push(...posts)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const posts = second_level[levels_key];
|
const posts = second_level[levels_key]!;
|
||||||
const parentEntry = {
|
const parentEntry = {
|
||||||
path: "",
|
path: "",
|
||||||
title: levels_key,
|
title: levels_key,
|
||||||
@ -91,9 +93,6 @@ for (const levels_key in second_level) {
|
|||||||
|
|
||||||
const index_page = entries.find(post => post.relative_file === "/index.md" || post.relative_file === "/index.mdx");
|
const index_page = entries.find(post => post.relative_file === "/index.md" || post.relative_file === "/index.mdx");
|
||||||
const basePath = index_page.url;
|
const basePath = index_page.url;
|
||||||
|
|
||||||
console.log(JSON.stringify(index_page, null, 4));
|
|
||||||
console.log(basePath);
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title={frontmatter.title}>
|
<BaseLayout title={frontmatter.title}>
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
---
|
---
|
||||||
import path from "path";
|
import NewDocsLayout, { type AstroFile } from "@/layouts/NewDocsLayout.astro";
|
||||||
import NewDocsLayout from "@/layouts/NewDocsLayout.astro";
|
|
||||||
|
|
||||||
const { frontmatter, headings } = Astro.props;
|
const { frontmatter, headings } = Astro.props;
|
||||||
// Get all the posts from this dir
|
// Get all the posts from this dir
|
||||||
const posts = await Astro.glob("./**/*.{md,mdx}");
|
|
||||||
|
const posts = await Astro.glob("./**/*.{md,mdx}") as unknown as Array<AstroFile>;
|
||||||
|
|
||||||
// Current dir
|
// Current dir
|
||||||
const current_dir = import.meta.dirname;
|
const current_dir = import.meta.dirname;
|
||||||
---
|
---
|
||||||
|
9
src/pages/en/latest/learn/classes/abstract.mdx
Normal file
9
src/pages/en/latest/learn/classes/abstract.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
layout: "../_wrapper.astro"
|
||||||
|
title: Abstract
|
||||||
|
---
|
||||||
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
|
# Abstract
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Anonymous classes
|
title: Anonymous classes
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Anonymous classes
|
# Anonymous classes
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Constructor/Destructor
|
title: Constructor/Destructor
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Constructor/Destructor
|
# Constructor/Destructor
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Basics
|
title: Basics
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Inheritance
|
title: Inheritance
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Inheritance
|
# Inheritance
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Interfaces
|
title: Interfaces
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Interfaces
|
# Interfaces
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Magic methods
|
title: Magic methods
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Magic methods
|
# Magic methods
|
||||||
|
|
15
src/pages/en/latest/learn/classes/readonly.mdx
Normal file
15
src/pages/en/latest/learn/classes/readonly.mdx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
layout: "../_wrapper.astro"
|
||||||
|
title: Readonly
|
||||||
|
---
|
||||||
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
|
# Readonly
|
||||||
|
|
||||||
|
<Code thpcode={`
|
||||||
|
class Caño
|
||||||
|
{
|
||||||
|
}
|
||||||
|
`} />
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Static
|
title: Static
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Static in classes
|
# Static in classes
|
||||||
|
|
7
src/pages/en/latest/learn/classes/visibility.mdx
Normal file
7
src/pages/en/latest/learn/classes/visibility.mdx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
layout: "../_wrapper.astro"
|
||||||
|
title: Visibility
|
||||||
|
---
|
||||||
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
|
# Visibility
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Arrays
|
title: Arrays
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Arrays
|
# Arrays
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Enums
|
title: Enums
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Enums
|
# Enums
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Maps
|
title: Maps
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Maps
|
# Maps
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Tuples
|
title: Tuples
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Tuples
|
# Tuples
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Tagged unions
|
title: Tagged unions
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Tagged unions
|
# Tagged unions
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Nullable types
|
title: Nullable types
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Nullable types
|
# Nullable types
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Try/Exceptions
|
title: Try/Exceptions
|
||||||
---
|
---
|
||||||
import InteractiveCode from "../../../components/InteractiveCode.astro";
|
import InteractiveCode from "@/components/InteractiveCode.astro";
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Try/exceptions
|
# Try/exceptions
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Blocks
|
title: Blocks
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Blocks
|
# Blocks
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Conditionals
|
title: Conditionals
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Conditionals
|
# Conditionals
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Loops
|
title: Loops
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Loops
|
# Loops
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Match
|
title: Match
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Match
|
# Match
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Declaration
|
title: Declaration
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Declaration
|
# Declaration
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Higher Order Functions
|
title: Higher Order Functions
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Higher Order functions
|
# Higher Order functions
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Lambdas
|
title: Lambdas
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Lambdas / Anonymous functions
|
# Lambdas / Anonymous functions
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Function parameters
|
title: Function parameters
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
|
|
||||||
# Function parameters
|
# Function parameters
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Components
|
title: Components
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
import Info from "../../../components/docs/Info.astro"
|
import Info from "@/components/docs/Info.astro"
|
||||||
|
|
||||||
# Components
|
# Components
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Control flow
|
title: Control flow
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
import Info from "../../../components/docs/Info.astro"
|
import Info from "@/components/docs/Info.astro"
|
||||||
|
|
||||||
# Control flow
|
# Control flow
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Introduction
|
title: Introduction
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
import Info from "../../../components/docs/Info.astro"
|
import Info from "@/components/docs/Info.astro"
|
||||||
|
|
||||||
# THP templating
|
# THP templating
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
layout: "../_wrapper.astro"
|
||||||
title: Props
|
title: Props
|
||||||
---
|
---
|
||||||
import Code from "../../../components/Code.astro"
|
import Code from "@/components/Code.astro"
|
||||||
import Info from "../../../components/docs/Info.astro"
|
import Info from "@/components/docs/Info.astro"
|
||||||
|
|
||||||
# Props
|
# Props
|
||||||
|
|
@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Comments
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Comments
|
|
||||||
|
|
||||||
THP supports single and multi line comments:
|
|
||||||
|
|
||||||
|
|
||||||
## Single line
|
|
||||||
|
|
||||||
Begin with double slash `//` and continue until the end of the line.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// This is a single line comment
|
|
||||||
print("hello!")
|
|
||||||
|
|
||||||
print("the result is {5 + 5}") // This will print 10
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
## Multi line
|
|
||||||
|
|
||||||
These begin with `/*` and end with `*/`. Everything in between is ignored.
|
|
||||||
|
|
||||||
Multi line comments can be nested in THP.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
/*
|
|
||||||
This is a
|
|
||||||
multiline comment
|
|
||||||
*/
|
|
||||||
`} />
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
/*
|
|
||||||
Multiline comments
|
|
||||||
can be /* nested */
|
|
||||||
*/
|
|
||||||
`} />
|
|
||||||
|
|
||||||
## Documentation comments
|
|
||||||
|
|
||||||
Documentation comments use triple slashes `///`.
|
|
||||||
These use [CommonMark Markdown](https://commonmark.org/) syntax.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
/// Transforms the format from A to B...
|
|
||||||
///
|
|
||||||
/// ## Errors
|
|
||||||
///
|
|
||||||
/// This function will error if condition
|
|
||||||
/// X or Y is met...
|
|
||||||
fun transform() {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Datatypes
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Datatypes
|
|
||||||
|
|
||||||
THP requires that all datatypes start their name with an
|
|
||||||
uppercase letter.
|
|
||||||
|
|
||||||
The following are basic datatypes.
|
|
||||||
|
|
||||||
## Int
|
|
||||||
|
|
||||||
Same as php int
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
Int age = 32
|
|
||||||
// Hexadecimal numbers start with 0x
|
|
||||||
Int red = 0xff0000
|
|
||||||
// Octal numbers start with 0o
|
|
||||||
Int permissions = 0o775
|
|
||||||
// Binary numbers start with 0b
|
|
||||||
Int char_code = 0b01000110
|
|
||||||
|
|
||||||
// IMPORTANT!
|
|
||||||
// Since Octal starts with \`0o\`, using just a leading 0
|
|
||||||
// will result in a decimal!
|
|
||||||
Int not_octal = 032 // This is 32, not 26
|
|
||||||
`} />
|
|
||||||
|
|
||||||
// TODO: Make it a compile error to have leading zeroes,
|
|
||||||
and force users to use `0o` for octal
|
|
||||||
|
|
||||||
|
|
||||||
## Float
|
|
||||||
|
|
||||||
Same as php float
|
|
||||||
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
Float pi = 3.141592
|
|
||||||
Float light = 2.99e+8
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
## String
|
|
||||||
|
|
||||||
THP strings use **only** double quotes. Single quotes are
|
|
||||||
used elsewhere.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
String name = "Rose"
|
|
||||||
`} />
|
|
||||||
|
|
||||||
Strings have interpolation with `{}`.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
print("Hello, {name}") // Hello, Rose
|
|
||||||
`} />
|
|
||||||
|
|
||||||
Unlike PHP, THP strings are concatenated with `++`, not with `.`.
|
|
||||||
This new operator implicitly converts any operator into a string.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
val name = "John" ++ " " ++ "Doe"
|
|
||||||
val greeting = "My name is " ++ name ++ " and I'm " ++ 32 ++ " years old"
|
|
||||||
`} />
|
|
||||||
|
|
||||||
The plus operator `+` is reserved for numbers.
|
|
||||||
|
|
||||||
|
|
||||||
## Bool
|
|
||||||
|
|
||||||
THP booleans are `true` and `false`. They are case sensitive,
|
|
||||||
**only lowercase.**
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
Bool is_true = true
|
|
||||||
Bool is_false = false
|
|
||||||
|
|
||||||
// This is a compile error
|
|
||||||
val invalid = TRUE
|
|
||||||
`} />
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Hello world
|
|
||||||
---
|
|
||||||
import InteractiveCode from "../../../components/InteractiveCode.astro";
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Hello, world!
|
|
||||||
|
|
||||||
## THP source code
|
|
||||||
|
|
||||||
Unlike PHP, THP code is written directly. There is no need to use any `<?php` tags,
|
|
||||||
just write the code like any other programming language.
|
|
||||||
|
|
||||||
As a consequence of this, HTML templates are defined in other ways, which will be
|
|
||||||
detailed later on.
|
|
||||||
|
|
||||||
To write a hello world program write the following code in a file:
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
print("Hello, world!")
|
|
||||||
`} />
|
|
||||||
|
|
||||||
Then run `thp hello.thp` from your terminal.
|
|
||||||
|
|
||||||
|
|
||||||
## Instruction separation
|
|
||||||
|
|
||||||
THP uses whitespace to determine when a statement is over. In short,
|
|
||||||
where PHP uses a semicolon `;`, THP uses a newline.
|
|
||||||
|
|
||||||
```php
|
|
||||||
echo("A");
|
|
||||||
echo("B");
|
|
||||||
echo("C");
|
|
||||||
```
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
print("A")
|
|
||||||
print("B")
|
|
||||||
print("C")
|
|
||||||
`} />
|
|
||||||
|
|
||||||
As a consequence of this, there can only be 1 statement per line.
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Operators
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Operators
|
|
||||||
|
|
||||||
|
|
||||||
Most of the PHP operators are present in THP.
|
|
||||||
|
|
||||||
## Numbers
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
var number = 322
|
|
||||||
|
|
||||||
number + 1
|
|
||||||
number - 1
|
|
||||||
number * 1
|
|
||||||
number / 1
|
|
||||||
number % 2
|
|
||||||
|
|
||||||
number += 1
|
|
||||||
number -= 1
|
|
||||||
number *= 1
|
|
||||||
number /= 1
|
|
||||||
number %= 2
|
|
||||||
`} />
|
|
||||||
|
|
||||||
**There are no prefix/postfix increment operators** (`++`, `--`),
|
|
||||||
use `+=` or `-=` instead.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// Use
|
|
||||||
number += 1
|
|
||||||
|
|
||||||
// instead of
|
|
||||||
number++ // This is a compile error
|
|
||||||
`} />
|
|
||||||
|
|
||||||
### Comparison
|
|
||||||
|
|
||||||
These operators will not do implicit type conversion. They can
|
|
||||||
only be used with same datatypes.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
v1 < v2
|
|
||||||
v1 <= v2
|
|
||||||
v1 > v2
|
|
||||||
v1 >= v2
|
|
||||||
`} />
|
|
||||||
|
|
||||||
There is only `==` and `!=`. They are equivalent to `===` and `!==`.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
v1 == v2
|
|
||||||
v1 != v2
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
### Bitwise
|
|
||||||
|
|
||||||
TBD
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
number and 1
|
|
||||||
number or 2
|
|
||||||
number xor 1
|
|
||||||
number xand 1
|
|
||||||
`} />
|
|
||||||
|
|
||||||
## Strings
|
|
||||||
|
|
||||||
Strings **do not use `.`** for concatenation. They use `++`.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
"Hello " ++ "world."
|
|
||||||
`} />
|
|
||||||
|
|
||||||
This new operator **implicitly converts** types to string
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
"Hello " ++ 322 // 322 will be converted to "322"
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
## Boolean
|
|
||||||
|
|
||||||
These operators work **only with booleans**, they do not perform
|
|
||||||
type coercion.
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
c1 && c2
|
|
||||||
c1 || c2
|
|
||||||
`} />
|
|
||||||
|
|
||||||
## Ternary
|
|
||||||
|
|
||||||
There is no ternary operator. See [Conditionals](/learn/flow-control/conditionals) for alternatives.
|
|
||||||
|
|
||||||
|
|
||||||
## Null
|
|
||||||
|
|
||||||
These are detailed in their section: [Nullable types](/learn/error-handling/null)
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
val person = some_fun()
|
|
||||||
|
|
||||||
person?.name
|
|
||||||
person?.name ?? "Jane"
|
|
||||||
person?.greet?.()
|
|
||||||
|
|
||||||
if person?
|
|
||||||
{
|
|
||||||
person.name
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Variables
|
|
||||||
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
|
|
||||||
THP distinguishes between mutable and immutable variables.
|
|
||||||
|
|
||||||
Variables must be declared in THP to avoid issues with scoping and
|
|
||||||
to know if they are mutable/immutable.
|
|
||||||
It's a compile error to use undeclared variables.
|
|
||||||
|
|
||||||
Variable names **don't** start with a dollar sign `$`.
|
|
||||||
|
|
||||||
Variable names **must** begin with a lowercase letter or an underscore.
|
|
||||||
Then they may contain lowercase/uppercase letters, numbers and underscores.
|
|
||||||
|
|
||||||
As a regex: `[a-z_][a-zA-Z0-9_]*`
|
|
||||||
|
|
||||||
## Immutable variables
|
|
||||||
|
|
||||||
Defined with `val`, followed by a variable name and a value.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
val surname = "Doe"
|
|
||||||
val year_of_birth = 1984
|
|
||||||
`} />
|
|
||||||
|
|
||||||
It's a compile error to attempt to modify it
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
val surname = "Doe"
|
|
||||||
surname = "Dane" // Error
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Datatype annotation
|
|
||||||
|
|
||||||
Written after the `val` keyword but before the variable name.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
val String surname = "Doe"
|
|
||||||
val Int year_of_birth = 1984
|
|
||||||
`} />
|
|
||||||
|
|
||||||
When annotating an immutable variable the `val` keyword is optional
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
// Equivalent to the previous code
|
|
||||||
String surname = "Doe"
|
|
||||||
Int year_of_birth = 1984
|
|
||||||
`} />
|
|
||||||
|
|
||||||
This means that if a variable only has a datatype, it is immutable.
|
|
||||||
|
|
||||||
It is a compile error to declare a variable of a datatype,
|
|
||||||
but use another.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
// Declare the variable as a String, but use a Float as its value
|
|
||||||
String capital = 123.456
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
## Mutable variables
|
|
||||||
|
|
||||||
Defined with `var`, followed by a variable name and a value.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
var name = "John"
|
|
||||||
var age = 32
|
|
||||||
|
|
||||||
age = 33
|
|
||||||
`} />
|
|
||||||
|
|
||||||
### Datatype annotation
|
|
||||||
|
|
||||||
Written after the `var` keywords but before the variable name.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
var String name = "John"
|
|
||||||
var Int age = 32
|
|
||||||
`} />
|
|
||||||
|
|
||||||
When annotating a mutable variable the keyword `var` is still **required**.
|
|
||||||
|
|
||||||
<Code level={2} thpcode={`
|
|
||||||
// Equivalent to the previous code
|
|
||||||
var String name = "John"
|
|
||||||
var Int age = 32
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,230 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../layouts/DocsLayout.astro
|
|
||||||
title: Cheatsheet
|
|
||||||
disable_container: true
|
|
||||||
---
|
|
||||||
import TwoColumn from "../../components/TwoColumn.astro"
|
|
||||||
import Code from "../../components/Code.astro"
|
|
||||||
|
|
||||||
# Language cheatsheet
|
|
||||||
|
|
||||||
Comparisons to PHP are noted.
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// THP code is written directly, it's not enclosed in any ?php tag
|
|
||||||
// Single line comments are written with two slashes
|
|
||||||
|
|
||||||
/*
|
|
||||||
Multiline comments use slash-asterisk
|
|
||||||
and can be /* nested */
|
|
||||||
*/
|
|
||||||
|
|
||||||
// there is no echo, only print
|
|
||||||
// Unlike PHP, parenthesis are required
|
|
||||||
print("Hello world")
|
|
||||||
`} />
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
// PHP requires a <?php opening tag
|
|
||||||
|
|
||||||
/*
|
|
||||||
PHP cannot nest multiline comments
|
|
||||||
/* this would be an error * /
|
|
||||||
*/
|
|
||||||
|
|
||||||
# PHP also has hash comments. THP doesn't
|
|
||||||
|
|
||||||
print "Hello world";
|
|
||||||
```
|
|
||||||
</TwoColumn>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Variables
|
|
||||||
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
|
|
||||||
<Code no_warnings={true} thpcode={`
|
|
||||||
// THP has explicit variable declaration
|
|
||||||
// Variables don't start with a dollar sign ($)
|
|
||||||
// Variables are declared with \`var\`
|
|
||||||
var age = 32
|
|
||||||
|
|
||||||
// Immutable variables are declared with \`val\`,
|
|
||||||
// and can't be reassigned
|
|
||||||
val name = "John"
|
|
||||||
|
|
||||||
// Variables may have a datatype declaration
|
|
||||||
// This is an immutable variable with a type
|
|
||||||
String road = "Abbey road"
|
|
||||||
// This is a mutable variable with a type
|
|
||||||
var String name = "The Beatles"
|
|
||||||
`} />
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
$age = 32;
|
|
||||||
|
|
||||||
|
|
||||||
// There is no PHP equivalent
|
|
||||||
$name = "John";
|
|
||||||
|
|
||||||
// You can't annotate the type of a variable in PHP
|
|
||||||
|
|
||||||
$road = "Abbey road";
|
|
||||||
|
|
||||||
$name = "The Beatles";
|
|
||||||
```
|
|
||||||
|
|
||||||
</TwoColumn>
|
|
||||||
|
|
||||||
## Datatypes
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
<Code no_warnings={true} thpcode={`
|
|
||||||
// Only double quotes, never single quotes
|
|
||||||
String name = "Jane"
|
|
||||||
// Interpolation
|
|
||||||
String full_name = "{name} Doe"
|
|
||||||
|
|
||||||
Int age = 25
|
|
||||||
Float interest = 3.22
|
|
||||||
|
|
||||||
// An integer with a leading zero is an error,
|
|
||||||
// you must use \`0o\` for octal
|
|
||||||
// Int invalid = 0755
|
|
||||||
Int valid = 0o755
|
|
||||||
|
|
||||||
// Case sensitive, only \`true\` or \`false\`
|
|
||||||
Bool has_a_cute_dress = true
|
|
||||||
`} />
|
|
||||||
```php
|
|
||||||
|
|
||||||
$name = 'Jane';
|
|
||||||
|
|
||||||
$full_name = "$name Doe";
|
|
||||||
|
|
||||||
$age = 25;
|
|
||||||
$interest = 3.22;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$invalid = 0755;
|
|
||||||
$valid = 0o755;
|
|
||||||
|
|
||||||
// PHP allows true/false in any case, for some reason
|
|
||||||
$has_a_cute_dress = TrUe;
|
|
||||||
```
|
|
||||||
</TwoColumn>
|
|
||||||
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
<Code no_warnings={true} thpcode={`
|
|
||||||
// String concatenation uses \`++\`
|
|
||||||
print("Hello " ++ "world")
|
|
||||||
|
|
||||||
// Basic operators
|
|
||||||
var res = 1 + 2 - 3 * 4 % 5
|
|
||||||
|
|
||||||
res += 2
|
|
||||||
res -= 2
|
|
||||||
res *= 2
|
|
||||||
res /= 2
|
|
||||||
res %= 2
|
|
||||||
|
|
||||||
// There are no prefix/postfix increment/decrement
|
|
||||||
//
|
|
||||||
//
|
|
||||||
`} />
|
|
||||||
```php
|
|
||||||
|
|
||||||
print("Hello " . "world");
|
|
||||||
|
|
||||||
|
|
||||||
$res = 1 + 2 - 3 * 4 % 5;
|
|
||||||
|
|
||||||
res += 2;
|
|
||||||
res -= 2;
|
|
||||||
res *= 2;
|
|
||||||
res /= 2;
|
|
||||||
res %= 2;
|
|
||||||
|
|
||||||
|
|
||||||
++res;
|
|
||||||
res--;
|
|
||||||
```
|
|
||||||
</TwoColumn>
|
|
||||||
|
|
||||||
## Flow control
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
<Code no_warnings={true} thpcode={`
|
|
||||||
// Parenthesis not required, braces required
|
|
||||||
if age < 18
|
|
||||||
{
|
|
||||||
print("Not allowed")
|
|
||||||
}
|
|
||||||
else if age == 18
|
|
||||||
{
|
|
||||||
print("Allowed, barely")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print("Allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conditionals are expressions
|
|
||||||
val gift = if prefers_silver
|
|
||||||
{
|
|
||||||
"silver necklace"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
"gold necklace"
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
```php
|
|
||||||
|
|
||||||
if (age < 18) {
|
|
||||||
print("Not allowed");
|
|
||||||
} else if (age === 18) {
|
|
||||||
print("Allowed, barely");
|
|
||||||
} else {
|
|
||||||
print("Allowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$gift = "";
|
|
||||||
if (prefers_silver) {
|
|
||||||
$gift = "silver necklace";
|
|
||||||
} else {
|
|
||||||
$gift = "gold necklace";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</TwoColumn>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<TwoColumn cols="grid-cols-[1fr_1fr] gap-2">
|
|
||||||
<Code no_warnings={true} thpcode={`
|
|
||||||
`} />
|
|
||||||
```php
|
|
||||||
```
|
|
||||||
</TwoColumn>
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Abstract
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Abstract
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Readonly
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Readonly
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
class Caño
|
|
||||||
{
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../../layouts/DocsLayout.astro
|
|
||||||
title: Visibility
|
|
||||||
---
|
|
||||||
import Code from "../../../components/Code.astro"
|
|
||||||
|
|
||||||
# Visibility
|
|
@ -1,251 +0,0 @@
|
|||||||
# Idea 1
|
|
||||||
|
|
||||||
|
|
||||||
let mut x = 20
|
|
||||||
let y = 30
|
|
||||||
|
|
||||||
type Something = ...
|
|
||||||
|
|
||||||
Something s1 = ...
|
|
||||||
Something s2 = s1
|
|
||||||
|
|
||||||
|
|
||||||
// Passes `some` by reference, but it's immutable. Cannot call mutable methods
|
|
||||||
// or use it in mutable operations
|
|
||||||
fun do_something(Something some) -> Bool {}
|
|
||||||
do_something(s1)
|
|
||||||
|
|
||||||
// Passes `some` by reference, and it's mutable. Can call mutable methods
|
|
||||||
// or use it in mutable operations
|
|
||||||
fun do_something(&Something some) -> Bool {}
|
|
||||||
do_something(&s1)
|
|
||||||
|
|
||||||
|
|
||||||
let mut arr1 = Array(10, 20, 30)
|
|
||||||
let mut arr2 = &arr1
|
|
||||||
|
|
||||||
|
|
||||||
Owned/Reference Mutable
|
|
||||||
Type Owned n
|
|
||||||
&Type Reference n
|
|
||||||
mut Type Owned y
|
|
||||||
&mut Type Reference y
|
|
||||||
|
|
||||||
|
|
||||||
Copy/Reference Mutable Equivalent
|
|
||||||
Some Copy n 1 (technically) references the other data
|
|
||||||
&Some Reference n 1 References the other data
|
|
||||||
mut Some Copy y 2 Creates a __mutable__ copy
|
|
||||||
&mut Some Reference y 3 References the other data, __mutable__
|
|
||||||
|
|
||||||
|
|
||||||
## `Array[A]::map`
|
|
||||||
|
|
||||||
```thp
|
|
||||||
fun map[B](this, (A) -> B callback) -> Array[B]
|
|
||||||
```
|
|
||||||
|
|
||||||
Applies `callback` to all the elements of this array, and
|
|
||||||
returns those new values in a new array.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```thp
|
|
||||||
let numbers = Array(1, 2, 3, 4, 5)
|
|
||||||
|
|
||||||
let numbers_squared = numbers.map {it ** 2}
|
|
||||||
|
|
||||||
print(numbers_squared) // Array(1, 4, 9, 16, 25)
|
|
||||||
|
|
||||||
numbers.map(fun(v) {
|
|
||||||
v - 2
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## `Array[A]::reduce`
|
|
||||||
|
|
||||||
```thp
|
|
||||||
fun reduce[B](
|
|
||||||
this,
|
|
||||||
B initial,
|
|
||||||
(A previous, B current) -> B callback,
|
|
||||||
) -> B
|
|
||||||
```
|
|
||||||
|
|
||||||
Iteratively reduce the array to a single value using `callback`.
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```thp
|
|
||||||
let numbers = Array(1, 2, 3, 4, 5)
|
|
||||||
|
|
||||||
let sum = numbers.reduce(0, \+)
|
|
||||||
let sum = numbers.reduce(0) {$1 + $2}
|
|
||||||
let sum = numbers.reduce(0, fun(prev, curr) {prev + curr})
|
|
||||||
|
|
||||||
print(sum) // 15
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```thp
|
|
||||||
let numbers = Array(1, 2, 3, 4, 5)
|
|
||||||
|
|
||||||
let sum = numbers.reduce("", fun(prev, curr) {prev + curr})
|
|
||||||
|
|
||||||
let sum = numbers.reduce("") {prev, curr -> prev + curr}
|
|
||||||
|
|
||||||
print(sum) // "12345"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```thp
|
|
||||||
// Functor
|
|
||||||
|
|
||||||
fun fmap(
|
|
||||||
(A) -> B,
|
|
||||||
f[A],
|
|
||||||
) -> f[B]
|
|
||||||
|
|
||||||
fun (<$)(
|
|
||||||
A,
|
|
||||||
f[B],
|
|
||||||
) -> f[A]
|
|
||||||
|
|
||||||
|
|
||||||
// Applicative
|
|
||||||
|
|
||||||
fun pure(A) -> f[A]
|
|
||||||
|
|
||||||
fun (<*>)(
|
|
||||||
f[A -> B],
|
|
||||||
f[A],
|
|
||||||
) -> f[B]
|
|
||||||
|
|
||||||
fun (*>)(
|
|
||||||
f[_],
|
|
||||||
f[B],
|
|
||||||
) -> f[B]
|
|
||||||
|
|
||||||
fun (<*)(
|
|
||||||
f[A],
|
|
||||||
f[_],
|
|
||||||
) -> f[A]
|
|
||||||
|
|
||||||
|
|
||||||
// Monad
|
|
||||||
|
|
||||||
fun (>>=)[m, A, B](
|
|
||||||
m[A],
|
|
||||||
(A) -> m[B],
|
|
||||||
) -> m[B]
|
|
||||||
|
|
||||||
|
|
||||||
(Array[Int], Int -> Array[String]) -> Array[String]
|
|
||||||
|
|
||||||
let result = Array(1, 2, 3, 4, 5) >>= {Array($.into[String]())}
|
|
||||||
|
|
||||||
print(result) // Array("1", "2", "3", "4", "5")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```thp
|
|
||||||
Option[Int] result = "322".try_into()
|
|
||||||
Option[Int] result_halved = result >>= {Some($ / 2)}
|
|
||||||
|
|
||||||
print(result_halved) // Some(161)
|
|
||||||
|
|
||||||
|
|
||||||
Option[Int] result = "abc".try_into()
|
|
||||||
Option[Int] result_halved = result >>= {Some($ / 2)}
|
|
||||||
|
|
||||||
print(result_halved) // None
|
|
||||||
```
|
|
||||||
|
|
||||||
```thp
|
|
||||||
fun (<$>)[m, A, B](
|
|
||||||
(A) -> B,
|
|
||||||
m[A],
|
|
||||||
) -> m[B]
|
|
||||||
|
|
||||||
|
|
||||||
fun half(Int x) -> Int {
|
|
||||||
x / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Option[Int] result = "322".try_into()
|
|
||||||
Option[Int] result_halved = result <$> half
|
|
||||||
|
|
||||||
print(result_halved) // Some(161)
|
|
||||||
|
|
||||||
|
|
||||||
Option[Int] result = "abc".try_into()
|
|
||||||
Option[Int] result_halved = result <$> half
|
|
||||||
|
|
||||||
print(result_halved) // None
|
|
||||||
```
|
|
||||||
|
|
||||||
```thp
|
|
||||||
fun (>>)[A, B, C](
|
|
||||||
(A) -> B,
|
|
||||||
(B) -> C,
|
|
||||||
) -> (A) -> C
|
|
||||||
|
|
||||||
let f1 = add1 >> times2
|
|
||||||
|
|
||||||
f1(5) // 12
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```thp
|
|
||||||
function_call[Datatype](param1, param2) {
|
|
||||||
// lambda
|
|
||||||
}
|
|
||||||
|
|
||||||
function_call([arr1, arr2])
|
|
||||||
function_call[Datatype]([arr1, arr2])
|
|
||||||
|
|
||||||
|
|
||||||
fun test[A, B](A a, B b) -> B {}
|
|
||||||
|
|
||||||
|
|
||||||
Array[String] v = 20
|
|
||||||
|
|
||||||
val x = Obj {
|
|
||||||
Array[Int] x: [1, 2, 3]
|
|
||||||
}
|
|
||||||
|
|
||||||
value + [1, 2, 3]
|
|
||||||
|
|
||||||
value + [Int]
|
|
||||||
|
|
||||||
|
|
||||||
value[0]
|
|
||||||
|
|
||||||
|
|
||||||
let functions = [
|
|
||||||
{0},
|
|
||||||
{1},
|
|
||||||
{2},
|
|
||||||
]
|
|
||||||
|
|
||||||
let index = 0
|
|
||||||
|
|
||||||
functions[index]()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
```thp
|
|
||||||
fun main()
|
|
||||||
{
|
|
||||||
// Using the turbofish operator
|
|
||||||
let result = "42".parse[Int]()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,305 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../layouts/DocsLayout.astro
|
|
||||||
title: Welcome
|
|
||||||
pagesLayout:
|
|
||||||
- path: index
|
|
||||||
- path: install
|
|
||||||
- path: cheatsheet
|
|
||||||
- path: basics
|
|
||||||
title: Basics
|
|
||||||
children:
|
|
||||||
- path: hello-world
|
|
||||||
- path: comments
|
|
||||||
- path: variables
|
|
||||||
- path: datatypes
|
|
||||||
- path: operators
|
|
||||||
- path: flow-control
|
|
||||||
title: Flow control
|
|
||||||
children:
|
|
||||||
- path: conditionals
|
|
||||||
- path: loops
|
|
||||||
- path: match
|
|
||||||
- path: blocks
|
|
||||||
- path: data-structures
|
|
||||||
title: Data structures
|
|
||||||
children:
|
|
||||||
- path: tuples
|
|
||||||
- path: arrays
|
|
||||||
- path: maps
|
|
||||||
- path: enums
|
|
||||||
- path: unions
|
|
||||||
- path: functions
|
|
||||||
title: Functions
|
|
||||||
children:
|
|
||||||
- path: declaration
|
|
||||||
- path: parameters
|
|
||||||
- path: higher-order
|
|
||||||
- path: lambdas
|
|
||||||
- path: error-handling
|
|
||||||
title: Error handling
|
|
||||||
children:
|
|
||||||
- path: "null"
|
|
||||||
- path: try
|
|
||||||
- path: classes
|
|
||||||
title: Classes
|
|
||||||
children:
|
|
||||||
- path: definition
|
|
||||||
- path: constructor
|
|
||||||
- path: inheritance
|
|
||||||
- path: static
|
|
||||||
- path: visibility
|
|
||||||
- path: readonly
|
|
||||||
- path: abstract
|
|
||||||
- path: interfaces
|
|
||||||
- path: anonymous
|
|
||||||
- path: magic
|
|
||||||
- path: templating
|
|
||||||
title: Templating
|
|
||||||
children:
|
|
||||||
- path: intro
|
|
||||||
- path: components
|
|
||||||
- path: props
|
|
||||||
- path: control-flow
|
|
||||||
---
|
|
||||||
import InteractiveCode from "../../components/InteractiveCode.astro";
|
|
||||||
import Code from "../../components/Code.astro"
|
|
||||||
|
|
||||||
|
|
||||||
# Welcome
|
|
||||||
|
|
||||||
Welcome to the documentation of the THP programming languague.
|
|
||||||
|
|
||||||
THP is a new programming language that compiles to PHP.
|
|
||||||
|
|
||||||
![Accurate visual description of THP](/img/desc_thp.jpg)
|
|
||||||
|
|
||||||
|
|
||||||
This page details the main design desitions of the language,
|
|
||||||
if you want to install THP go to the [installation guide](install)
|
|
||||||
|
|
||||||
|
|
||||||
## Why?
|
|
||||||
|
|
||||||
PHP is an old language. It has been growing since 1995, adopting a
|
|
||||||
lot of features from many places like C, Perl, Java, etc. This was
|
|
||||||
done in a very inconsistent way, as detailed by Eevee in their article
|
|
||||||
[PHP: a fractal of bad design.](https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/)
|
|
||||||
|
|
||||||
Along the years PHP has been improving. PHP added classes, exceptions,
|
|
||||||
interfaces, traits, type hints and checks, functional features,
|
|
||||||
reflection, etc., etc. However, by building on top of the existing
|
|
||||||
language without a clear design philosophy, and by keeping backwards
|
|
||||||
compatibility, we ended up with a messy language. The article
|
|
||||||
above goes into detail about this.
|
|
||||||
|
|
||||||
In spite of this, PHP has remained widely used and loved, in a
|
|
||||||
weird way (I'd say in the same way that people love JavaScript),
|
|
||||||
and at the time of writing PHP 8.3 is available. However,
|
|
||||||
PHP is to my eyes fundamentally flawed, and cannot get up to
|
|
||||||
date without completely breaking what came before.
|
|
||||||
|
|
||||||
This is where THP comes in. I wanted a modern language
|
|
||||||
that could run in the same environment that PHP does.
|
|
||||||
And I quickly realized that building on top of PHP
|
|
||||||
in the same way that TypeScript did for JavaScript would be
|
|
||||||
detrimental. It would be better to create a completely new
|
|
||||||
language, treat PHP source code as a "low level" compilation
|
|
||||||
target, and focus entirely on the new language.
|
|
||||||
|
|
||||||
This new language would be mainly inspired by what **I** consider the best
|
|
||||||
designed languages out there: Rust as a baseline, Zig for
|
|
||||||
its null and error handling and Kotlin for its OOP features.
|
|
||||||
In a way, PHP will be adapted to, say, Rust's syntax and semantics,
|
|
||||||
instead of having Rust adapt to PHP.
|
|
||||||
|
|
||||||
In pursue of this THP **will** ditch many things about PHP,
|
|
||||||
in name of consistency. These are things that PHP devs are
|
|
||||||
used to doing, but that I consider bad practices, hacks or
|
|
||||||
workarounds. One example of this are variable variables on PHP:
|
|
||||||
`$$variable`.
|
|
||||||
|
|
||||||
Another critical point of THP is type safety. It is a goal
|
|
||||||
to approach the same level of type safety that have compiled
|
|
||||||
languages like Java/Go/Rust, and leave aside dynamic typing
|
|
||||||
as much as possible. Types cannot be turned off, you cannot
|
|
||||||
use `Any` to avoid typechecking, and so on.
|
|
||||||
|
|
||||||
Finally, there are some additions to the language that I consider
|
|
||||||
essential today: A good, unified LSP, type definitions,
|
|
||||||
accesible documentation, an opinionated code formatter
|
|
||||||
and plugins for major editors like VSCode and Neovim.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Goals
|
|
||||||
|
|
||||||
- Bring static typing to PHP: Generics, type checks at compile and runtime, etc.
|
|
||||||
- Reduce implicit type conversion to a minimum.
|
|
||||||
- Remove the inconsistencies in the language.
|
|
||||||
- Organize the PHP stdlib.
|
|
||||||
- Have a clear distinctions between Arrays, Tuples, Maps and Sets.
|
|
||||||
- Implement Union types
|
|
||||||
- Create a **consistent** language.
|
|
||||||
- Have typings for popular libraries (like TS's `.d.ts`).
|
|
||||||
- Have a simple instalation and configuration (requiring just Composer or a binary).
|
|
||||||
- Ship a **_blazingly fast_**, native binary, ~~written in Rust~~ now rewritten in Zig!.
|
|
||||||
- Support in-place compilation.
|
|
||||||
- Implement a Language Server.
|
|
||||||
- Implement an opinionated code formatter.
|
|
||||||
|
|
||||||
![Friendship ended with Rust, now Zig is my best friend.](/img/mudasir.jpg)
|
|
||||||
|
|
||||||
|
|
||||||
## Not goals
|
|
||||||
|
|
||||||
These are **not** things that THP wants to solve or implement
|
|
||||||
|
|
||||||
- Be what TypeScript is for JavaScript (PHP with types).
|
|
||||||
- Strictly adhere to PHP syntax/conventions.
|
|
||||||
|
|
||||||
THP **_intentionally_** uses a different syntax from PHP to signal
|
|
||||||
that it is a different language, and has different semantics.
|
|
||||||
|
|
||||||
|
|
||||||
## Some differences with PHP
|
|
||||||
|
|
||||||
```php
|
|
||||||
// PHP
|
|
||||||
$has_key = str_contains($haystack, 'needle');
|
|
||||||
print("has key? " . $has_key);
|
|
||||||
```
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// THP
|
|
||||||
val has_key = haystack.contains("needle")
|
|
||||||
print("has key? " + has_key)
|
|
||||||
`} />
|
|
||||||
|
|
||||||
- Explicit variable declaration
|
|
||||||
- No `$` for variable names (and thus no `$$variable`, use a map instead)
|
|
||||||
- No semicolons
|
|
||||||
- Use methods on common datatypes
|
|
||||||
- Strings use only double quotes
|
|
||||||
- String concatenation with `+`
|
|
||||||
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
```php
|
|
||||||
// PHP
|
|
||||||
$obj = [
|
|
||||||
'names' => ['Toni', 'Stark'],
|
|
||||||
'age' => 33,
|
|
||||||
'numbers' => [32, 64, 128]
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// THP
|
|
||||||
val obj = .{
|
|
||||||
names: #("Toni", "Stark"), // Tuple
|
|
||||||
age: 33,
|
|
||||||
numbers: [32, 64, 128]
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
- Tuples, Arrays, Sets, Maps are clearly different
|
|
||||||
- JSON-like object syntax
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
```php
|
|
||||||
// PHP
|
|
||||||
$cat = new Cat("Michifu", 7);
|
|
||||||
$cat->meow();
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// THP
|
|
||||||
val cat = Cat("Michifu", 7)
|
|
||||||
cat.meow()
|
|
||||||
`} />
|
|
||||||
|
|
||||||
- Instantiate classes without `new`
|
|
||||||
- Use dot `.` instead of arrow `->` syntax
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
```php
|
|
||||||
// PHP
|
|
||||||
use \Some\Deeply\Nested\Class
|
|
||||||
use \Some\Deeply\Nested\Interface
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// THP
|
|
||||||
use Some::Deeply::Nested::{Class, Interface}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
- Different module syntax
|
|
||||||
- Explicit module declaration
|
|
||||||
- PSR-4 required
|
|
||||||
- No `include`, `include_once`, `require` or `require_once`
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
|
|
||||||
Other things:
|
|
||||||
|
|
||||||
- Pattern matching
|
|
||||||
- ADTs
|
|
||||||
|
|
||||||
|
|
||||||
## Runtime changes
|
|
||||||
|
|
||||||
Where possible THP will compile to available PHP functions/classes/methods/etc.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
<Code thpcode={`
|
|
||||||
// This expression
|
|
||||||
val greeting =
|
|
||||||
match get_person()
|
|
||||||
case Some(person) if person.age > 18
|
|
||||||
{
|
|
||||||
"Welcome, {person.name}"
|
|
||||||
}
|
|
||||||
case Some(person)
|
|
||||||
{
|
|
||||||
"I'm sorry {person.name}, you need to be 18 or older"
|
|
||||||
}
|
|
||||||
case None
|
|
||||||
{
|
|
||||||
"Nobody is here"
|
|
||||||
}
|
|
||||||
`} />
|
|
||||||
|
|
||||||
```php
|
|
||||||
// Would compile to:
|
|
||||||
$greeting = null;
|
|
||||||
$_person = get_person();
|
|
||||||
if ($_person !== null) {
|
|
||||||
if ($_person["age"] > 18) {
|
|
||||||
$greeting = "Welcome, " . $_person["name"];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$greeting = "I'm sorry " . $_person["name"] . ", you need to be 18 or older";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$greeting = "Nobody is here";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
However, more advanced datatypes & helper functions will require a sort of
|
|
||||||
runtime (new classes/functions/etc) or abuse the language's syntax/semantics.
|
|
||||||
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../layouts/DocsLayout.astro
|
|
||||||
title: Install
|
|
||||||
---
|
|
||||||
|
|
||||||
# Install
|
|
||||||
|
|
||||||
**THP is technically usable.**
|
|
||||||
|
|
||||||
## From source (*nix)
|
|
||||||
|
|
||||||
Requires Rust installed.
|
|
||||||
|
|
||||||
Clone [the repo](https://git.araozu.dev/fernando/thp) and run
|
|
||||||
`cargo build --release`. You'll have a `thp` binary on
|
|
||||||
`target/release/thp`, run it and see for yourself.
|
|
||||||
|
|
||||||
|
|
||||||
## Binary
|
|
||||||
|
|
||||||
Goal: Install THP with a single binary. Assumes that php and composer is
|
|
||||||
available.
|
|
||||||
|
|
||||||
|
|
||||||
## With composer
|
|
||||||
|
|
||||||
TBD: Install THP with `composer require thp`
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user