feat: Add docs
This commit is contained in:
parent
3f388b8e22
commit
e6df715955
@ -9,8 +9,7 @@ const [native_html, error_type, error_message] = await native_highlighter(thpcod
|
|||||||
---
|
---
|
||||||
|
|
||||||
<pre
|
<pre
|
||||||
class="language-thp"><code class="language-thp" set:html={native_html} /><span class="absolute top-2 right-2 inline-block text-sm select-none opacity-75">thp
|
class="language-thp"><code class="language-thp" set:html={native_html} /><span class="absolute top-1 right-1 text-right inline-block text-sm select-none opacity-75">thp</span></pre>
|
||||||
</span></pre>
|
|
||||||
{
|
{
|
||||||
no_warnings !== true && error_message !== null && (
|
no_warnings !== true && error_message !== null && (
|
||||||
<CodeError error_type={error_type} error_message={error_message} />
|
<CodeError error_type={error_type} error_message={error_message} />
|
||||||
|
@ -30,18 +30,24 @@ const { showSidebarButton = true } = Astro.props;
|
|||||||
>
|
>
|
||||||
Learn
|
Learn
|
||||||
</a>
|
</a>
|
||||||
|
<a
|
||||||
|
href="/api/std/"
|
||||||
|
class="hidden sm:inline-block px-4 font-display font-bold-text-xl hover:underline"
|
||||||
|
>
|
||||||
|
Standard Library
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/api/help/"
|
||||||
|
class="hidden sm:inline-block px-4 font-display font-bold-text-xl hover:underline"
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</a>
|
||||||
<a
|
<a
|
||||||
href="/spec/"
|
href="/spec/"
|
||||||
class="hidden sm:inline-block px-4 font-display font-bold-text-xl hover:underline"
|
class="hidden sm:inline-block px-4 font-display font-bold-text-xl hover:underline"
|
||||||
>
|
>
|
||||||
Language spec
|
Language spec
|
||||||
</a>
|
</a>
|
||||||
<a
|
|
||||||
href="/api/std/"
|
|
||||||
class="hidden sm:inline-block px-4 font-display font-bold-text-xl hover:underline"
|
|
||||||
>
|
|
||||||
std reference
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
<div class="two-column grid grid-cols-[10rem_auto]">
|
---
|
||||||
|
const {cols} = Astro.props;
|
||||||
|
const grid_cols = cols ?? "grid-cols-[10rem_auto]";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class={`two-column grid ${grid_cols}`}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,7 @@ const indexSubpath = `/learn/index.mdx`;
|
|||||||
posts={posts}
|
posts={posts}
|
||||||
indexSubpath={indexSubpath}
|
indexSubpath={indexSubpath}
|
||||||
basePath="/learn/"
|
basePath="/learn/"
|
||||||
|
disable_container={!!frontmatter.disable_container}
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</PagesLayout>
|
</PagesLayout>
|
||||||
|
@ -10,6 +10,7 @@ const {
|
|||||||
posts: _posts,
|
posts: _posts,
|
||||||
indexSubpath,
|
indexSubpath,
|
||||||
basePath,
|
basePath,
|
||||||
|
disable_container,
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
const posts: Record<string, any>[] = _posts;
|
const posts: Record<string, any>[] = _posts;
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ for (const entry of pagesIndex) {
|
|||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="lg:grid lg:grid-cols-[14rem_auto_12rem] lg:container mx-auto font-display"
|
class={`lg:grid lg:grid-cols-[14rem_auto_12rem] ${disable_container? "": "lg:container"} mx-auto font-display`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
id="sidebar"
|
id="sidebar"
|
||||||
@ -95,7 +96,7 @@ for (const entry of pagesIndex) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main
|
<main
|
||||||
class="py-[3.5rem] lg:pl-12 lg:pr-4 markdown min-w-0 small-container mx-auto"
|
class="pt-[3.5rem] pb-[10rem] lg:pl-12 lg:pr-4 markdown min-w-0 small-container mx-auto"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
import { leftTrimDedent } from "../components/utils";
|
import { leftTrimDedent } from "../components/utils";
|
||||||
import { HighlightLevel } from "./types";
|
import { HighlightLevel } from "./types";
|
||||||
import type { LexError, SyntaxError, Token, TokenizeResult, TokenType } from "./types";
|
import type { MistiErr, Token, TokenizeResult, TokenType } from "./types";
|
||||||
|
|
||||||
const error_classes = "underline underline-offset-4 decoration-wavy decoration-red-500";
|
const error_classes = "underline underline-offset-4 decoration-wavy decoration-red-500";
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ export async function native_highlighter(code: string, level = HighlightLevel.Sy
|
|||||||
let result = await native_lex(formatted_code);
|
let result = await native_lex(formatted_code);
|
||||||
return highlight_syntax(formatted_code, result, level);
|
return highlight_syntax(formatted_code, result, level);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return compiler_error(formatted_code, error as Error);
|
return compiler_error(formatted_code, error as MistiErr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ function highlight_syntax(code: string, result: TokenizeResult, level: Highlight
|
|||||||
const [tokens, semanticError] = result.SemanticError;
|
const [tokens, semanticError] = result.SemanticError;
|
||||||
|
|
||||||
if (level === HighlightLevel.Semantic) {
|
if (level === HighlightLevel.Semantic) {
|
||||||
return semantic_error_highlighter(code, tokens, semanticError.Semantic!);
|
return semantic_error_highlighter(code, tokens, semanticError);
|
||||||
} else {
|
} else {
|
||||||
tokens_final = tokens;
|
tokens_final = tokens;
|
||||||
}
|
}
|
||||||
@ -31,13 +31,13 @@ function highlight_syntax(code: string, result: TokenizeResult, level: Highlight
|
|||||||
const [tokens, syntaxError] = result.SyntaxError;
|
const [tokens, syntaxError] = result.SyntaxError;
|
||||||
|
|
||||||
if (level === HighlightLevel.Semantic || level === HighlightLevel.Syntactic) {
|
if (level === HighlightLevel.Semantic || level === HighlightLevel.Syntactic) {
|
||||||
return syntax_error_highlighter(code, tokens, syntaxError.Syntax!);
|
return syntax_error_highlighter(code, tokens, syntaxError);
|
||||||
} else {
|
} else {
|
||||||
tokens_final = tokens;
|
tokens_final = tokens;
|
||||||
}
|
}
|
||||||
} else if (result.LexError) {
|
} else if (result.LexError) {
|
||||||
// There is no error level that bypasses a lex error
|
// There is no error level that bypasses a lex error
|
||||||
return lex_error_highlighter(code, result.LexError!.Lex!);
|
return lex_error_highlighter(code, result.LexError!);
|
||||||
} else if (result.Ok) {
|
} else if (result.Ok) {
|
||||||
tokens_final = result.Ok;
|
tokens_final = result.Ok;
|
||||||
} else {
|
} else {
|
||||||
@ -56,7 +56,7 @@ function highlight_syntax(code: string, result: TokenizeResult, level: Highlight
|
|||||||
/**
|
/**
|
||||||
* Highlights code that has a lexic error
|
* Highlights code that has a lexic error
|
||||||
*/
|
*/
|
||||||
function lex_error_highlighter(code: string, error: LexError): [string, string, string] {
|
function lex_error_highlighter(code: string, error: MistiErr): [string, string, string] {
|
||||||
// Create a single error token
|
// Create a single error token
|
||||||
|
|
||||||
const err_pos = error.position;
|
const err_pos = error.position;
|
||||||
@ -73,7 +73,7 @@ function lex_error_highlighter(code: string, error: LexError): [string, string,
|
|||||||
return [all, "Lexical", error.reason + ` at line ${error_line}:${error_column} `]
|
return [all, "Lexical", error.reason + ` at line ${error_line}:${error_column} `]
|
||||||
}
|
}
|
||||||
|
|
||||||
function syntax_error_highlighter(code: string, tokens: Array<Token>, error: SyntaxError): [string, string, string] {
|
function syntax_error_highlighter(code: string, tokens: Array<Token>, error: MistiErr): [string, string, string] {
|
||||||
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
||||||
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ function syntax_error_highlighter(code: string, tokens: Array<Token>, error: Syn
|
|||||||
return [highlighted, "Syntax", error_message];
|
return [highlighted, "Syntax", error_message];
|
||||||
}
|
}
|
||||||
|
|
||||||
function semantic_error_highlighter(code: string, tokens: Array<Token>, error: SyntaxError): [string, string, string] {
|
function semantic_error_highlighter(code: string, tokens: Array<Token>, error: MistiErr): [string, string, string] {
|
||||||
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
const highlighted = highlight_tokens(code, tokens, error.error_start, error.error_end);
|
||||||
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
const [error_line, error_column] = absolute_to_line_column(code, error.error_start);
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ function semantic_error_highlighter(code: string, tokens: Array<Token>, error: S
|
|||||||
return [highlighted, "Semantic", error_message];
|
return [highlighted, "Semantic", error_message];
|
||||||
}
|
}
|
||||||
|
|
||||||
function compiler_error(code: string, error: Error): [string, string, string] {
|
function compiler_error(code: string, error: MistiErr): [string, string, string] {
|
||||||
return [code, "Fatal Compiler", error.message];
|
return [code, "Fatal Compiler", error.message];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +225,6 @@ function translate_token_type(tt: TokenType, value: string): string {
|
|||||||
case "FOR":
|
case "FOR":
|
||||||
case "IN":
|
case "IN":
|
||||||
case "WHILE":
|
case "WHILE":
|
||||||
case "LOOP":
|
|
||||||
case "MATCH":
|
case "MATCH":
|
||||||
case "CASE":
|
case "CASE":
|
||||||
return "keyword";
|
return "keyword";
|
||||||
|
@ -43,38 +43,29 @@ export type TokenType =
|
|||||||
| "CASE"
|
| "CASE"
|
||||||
;
|
;
|
||||||
|
|
||||||
export interface Err {
|
export interface MistiErr {
|
||||||
Lex?: LexError
|
error_code: number
|
||||||
Syntax?: SyntaxError
|
error_offset: number
|
||||||
Semantic?: SemanticError
|
labels: Array<ErrorLabel>
|
||||||
|
note: string | null,
|
||||||
|
help: string | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LexError {
|
export interface ErrorLabel {
|
||||||
position: number
|
message: string
|
||||||
reason: string
|
start: number
|
||||||
}
|
end: number
|
||||||
|
|
||||||
export interface SyntaxError {
|
|
||||||
error_start: number
|
|
||||||
error_end: number
|
|
||||||
reason: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SemanticError {
|
|
||||||
error_start: number
|
|
||||||
error_end: number
|
|
||||||
reason: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenizeResult {
|
export interface TokenizeResult {
|
||||||
/** All checks passed */
|
/** All checks passed */
|
||||||
Ok?: Array<Token>,
|
Ok?: Array<Token>,
|
||||||
/** There were semantic errors */
|
/** There were semantic errors */
|
||||||
SemanticError?: [Array<Token>, Err],
|
SemanticError?: [Array<Token>, MistiErr],
|
||||||
/** There were syntax errors */
|
/** There were syntax errors */
|
||||||
SyntaxError?: [Array<Token>, Err],
|
SyntaxError?: [Array<Token>, MistiErr],
|
||||||
/** No checks passed */
|
/** No checks passed */
|
||||||
LexError?: Err,
|
LexError?: MistiErr,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum HighlightLevel {
|
export enum HighlightLevel {
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
---
|
|
||||||
layout: ../../layouts/DocsLayout.astro
|
|
||||||
title: Cheatsheet
|
|
||||||
---
|
|
||||||
|
|
||||||
# Language cheatsheet
|
|
||||||
|
|
||||||
Comparisons to PHP are noted.
|
|
||||||
|
|
||||||
```thp
|
|
||||||
// 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 */
|
|
||||||
*/
|
|
||||||
|
|
||||||
// print writes input to stdout in terminal mode
|
|
||||||
print("Hello world")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Types and variables
|
|
||||||
|
|
||||||
```thp
|
|
||||||
// Variables are always declared
|
|
||||||
// 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"
|
|
||||||
|
|
||||||
// A variable name starts with either a:
|
|
||||||
// - lowercase letter
|
|
||||||
// - underscore
|
|
||||||
// and then may contain any letter, underscore or number
|
|
||||||
val my_variable = "my value"
|
|
||||||
|
|
||||||
// Datatypes' names start with an uppercase letter, always
|
|
||||||
// A declaration may optionally specifiy its datatype, after
|
|
||||||
// the var/val keyword
|
|
||||||
var String lastname = "Doe"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Bool
|
|
||||||
//
|
|
||||||
|
|
||||||
// Booleans are only `true` and `false`, case sensitive
|
|
||||||
val condition = true
|
|
||||||
val accepted = false
|
|
||||||
|
|
||||||
//
|
|
||||||
// Int
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
230
src/pages/learn/cheatsheet.mdx
Normal file
230
src/pages/learn/cheatsheet.mdx
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
---
|
||||||
|
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>
|
@ -152,7 +152,7 @@ and plugins for major editors like VSCode and Neovim.
|
|||||||
|
|
||||||
## Not goals
|
## Not goals
|
||||||
|
|
||||||
These are **not** aspects that THP looks to solve or implement.
|
These are **not** things that THP wants to solve or implement
|
||||||
|
|
||||||
- Be what TypeScript is for JavaScript (PHP with types).
|
- Be what TypeScript is for JavaScript (PHP with types).
|
||||||
- Strictly adhere to PHP syntax/conventions.
|
- Strictly adhere to PHP syntax/conventions.
|
||||||
|
@ -7,11 +7,13 @@ title: Install
|
|||||||
|
|
||||||
**THP is not available for public use. These are goals.**
|
**THP is not available for public use. These are goals.**
|
||||||
|
|
||||||
## From scratch
|
## Binary
|
||||||
|
|
||||||
|
Goal: Install THP with a single binary. Assumes that php and composer is
|
||||||
|
available.
|
||||||
|
|
||||||
Also install php (through XAMPP in windows/mac, php in linux) and Composer.
|
|
||||||
|
|
||||||
## With composer
|
## With composer
|
||||||
|
|
||||||
TBD, the user should be able to just run `composer require thp` and
|
TBD: Install THP with `composer require thp`
|
||||||
the proper binary should be intalled.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user