We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
FlamePL
The current version of FlamePL is 1.2. In version 1.3, more STLibs will be added.
FlamePL is designed by PSTF and his AI assistant.
Overview
FlamePL is a programming language for data analysis and software developing.
Syntax
Formal EBNF Grammar
(* Lexical tokens (terminals) *)
letter = "A" | "B" | ... | "Z" | "a" | "b" ... | "z" ;
digit = "0" | "1" | ... | "9" ;
ident = letter , { letter | digit | "_" } ;
number = digit , { digit } , [ "." , { digit } ] ;
imag = digit , { digit } , "i" ;
string = '"' , { character - '"' } , '"' |
'"""' , { character } , '"""' ;
comment = "#" , { character - newline } ;
(* Keywords – they are reserved *)
keyword = "fn" | "class" | "if" | "then" | "else" | "end" |
"while" | "do" | "return" | "null" | "lambda" |
"and" | "or" | "not" | "true" | "false" |
"print" | "input" | "to_int" | "to_float" |
"to_str" | "type_of" | "for" | "in" ;
(* Operators and delimiters *)
op_assign = "<-" ;
op_eq = "=" ;
op_exp = "^" ;
op_idiv = "//" ;
op_mod = "%"
op_add = "+" | "-" ;
op_mul = "*" | "/" | "//" | "%" ;
op_cmp = "=" | "<" | ">" ;
delim = "(" | ")" | "[" | "]" | "{" | "}" | ":" | "," | "." | "->" ;
(* ==================== Syntax rules ==================== *)
program = { statement } ;
statement = assignment
| if_statement
| for_statement
| while_statement
| return_statement
| function_def
| class_def
| import_statement
| expression ;
assignment = ident , "<-" , expression ;
if_statement = "if" , expression , "then" , { statement } ,
[ "else" , { statement } ] , "end" ;
for_statement = "for" , ident , "in" , expression , "do" ,
{ statement } , "end" ;
while_statement = "while" , expression , "do" , { statement } , "end" ;
return_statement = "return" , expression ;
function_def = "fn" , ident , "(" , [ ident , { "," , ident } ] , ")" ,
{ statement } , "end" ;
class_def = "class" , ident , [ ":" , ident ] ,
{ function_def } , "end" ;
import_name = string | ident ;
import_spec = import_name , [ "as" , ident ] ;
from_import = "from" , import_name , "import" , import_spec , { "," , import_spec } ;
import_statement = "import" , import_name
| from_import ;
(* expression – precedence from lowest to highest *)
expression = or_expr ;
or_expr = and_expr , { "or" , and_expr } ;
and_expr = not_expr , { "and" , not_expr } ;
not_expr = "not" , not_expr | comparison_expr ;
comparison_expr = additive_expr , [ ("=" | "<" | ">") , additive_expr ] ;
additive_expr = multiplicative_expr , { ("+" | "-") , multiplicative_expr } ;
multiplicative_expr = power_expr , { ("*" | "/" | "//") , power_expr } ;
power_expr = unary_expr , [ "^" , power_expr ] ; (* right‑associative *)
unary_expr = ("+" | "-") , unary_expr | postfix_expr ;
postfix_expr = primary_expr ,
{ "[" , expression , "]"
| "(" , [ expression , { "," , expression } ] , ")"
| "." , ident , "(" , [ expression , { "," , expression } ] , ")"
} ;
primary_expr = number
| imag
| string
| "true"
| "false"
| "null"
| "(" , expression , [ "," , expression ] , ")"
| "[" , [ expression , { "," , expression } ] , "]"
| "{" , [ expression , ":" , expression , { "," , expression , ":" , expression } ] , "}"
| "lambda" , "(" , [ ident , { "," , ident } ] , ")" , "->" , expression
| ident
| "to_int" , "(" , expression , ")"
| "to_float" , "(" , expression , ")"
| "to_str" , "(" , expression , ")"
| "type_of" , "(" , expression , ")"
| "print" , "(" , expression , ")"
| "input" , "(" , expression , ")" ;
Textual Description of Semantics
1. Lexical Conventions
- Comments start with
#and run to the end of the line; they are ignored. - Identifiers are case‑sensitive and start with a letter or underscore, followed by letters, digits, or underscores.
- Keywords (
fn,class,if,then,else,end,while,do,return,null,lambda,and,or,not,true,false,print,input,to_int,to_float,to_str,type_of) are reserved. - Numbers are arbitrary‑precision decimals (implemented via Python’s
Decimal). They can be integers or floating‑point. - Imaginary literals are digits followed by
i(e.g.3i,42i) and denote a complex number with zero real part. - Strings are delimited by double quotes
"for single‑line strings, and by triple double‑quotes"""for multi‑line strings. Escape sequences are not processed – they are literal. - Whitespace (spaces, tabs, newlines) is ignored except for separating tokens.
2. Data Types
| Type | Syntax / Example | Notes |
|---|---|---|
| Integer | 42, -3
|
Arbitrary precision; stored as Decimal with exponent 0.
|
| Float | 3.14, 2.71828
|
Arbitrary‑precision decimal floating point. |
| Complex | 3+4i, -2.5i
|
Real and imaginary parts are arbitrary‑precision decimals. |
| String | "hello", """multi
|
Unicode strings. |
| Boolean | true, false
|
Distinct type; results of logical/comparison ops. |
| List | [1, 2, 3]
|
Ordered, mutable, heterogeneous. |
| Pair | (10, 20)
|
Fixed‑size ordered pair of two values. |
| Dictionary | {"name": "FlamePL", "ver": 1}
|
Key‑value mapping; keys can be any type. |
| Null | null
|
Represents the absence of a value. |
| Function | created by fn or lambda
|
First‑class, closures, recursive. |
| Class / Instance | class ... end
|
Supports inheritance and methods. |
| Type | returned by type_of
|
First‑class type objects (int, float, bool, …).
|
3. Variables and Scope
- Assignment:
x <- 10— binds a value to a name in the current scope. - Equality test:
x = 10— returns a Boolean; not an assignment. - Scopes: Functions create new lexical scopes that capture their enclosing environment (closures). Blocks (
if,while,do) do not create new scopes – they share the surrounding scope. - Variable lookup searches the current scope, then outer scopes recursively.
4. Expressions
Arithmetic Operators
+,-,*,/— standard numeric operations (work on integers, floats, complex).^— exponentiation (right‑associative):2 ^ 3 ^ 2→2 ^ (3 ^ 2).//— integer division (floor division) for numeric types.%— modulo for numeric types.- Unary
+and-are supported.
Comparison Operators
=,<,>— all return Booleans.=is equality, never assignment.
Logical Operators
and,or,not— short‑circuiting, always return a Boolean (trueorfalse).
Example: true and false → false, not true → false.
Type Conversion (built‑in functions)
to_int(x)— converts to integer (truncates floats, parses strings).to_float(x)— converts to arbitrary‑precision float.to_str(x)— returns a string representation.
Type Inspection
type_of(x)— returns a first‑class type object (e.g.int,bool,list). These type objects can be compared with=.
5. Control Flow
Conditional
if condition then
statements
else
statements
end
The else block is optional. The condition must evaluate to a Boolean.
Conditional Loop
while condition do
statements
end
Loops while the condition is true; condition evaluated before each iteration.
For-loop
for var in iterable do
statements
end
- Var is a variable name that takes each element of iterable in turn.
- Iterable can be a list, a string (iterates over characters), or a dictionary (iterates over keys).
- The body is a block of statements; the variable is rebound in the current scope (no new scope is created, but assignments inside affect the surrounding environment).
- The loop runs until all elements are exhausted.
Return
return expression — exits the current function and returns the value. If used outside a function, it is an error.
6. Functions and Lambdas
Named Function
fn add(a, b)
return a + b
end
- Parameters are passed by value.
- The function body is a sequence of statements.
- The last evaluated expression is not implicitly returned; you must use
return.
Lambda (Anonymous)
square <- lambda (x) -> x * x
- A lambda consists of a parameter list,
->, and a single expression (not a block). - Lambdas are closures.
Recursion
Functions may call themselves by name; the name is resolved lexically.
7. Object‑Oriented Programming
class Animal
fn init(name)
self.name <- name
end
fn speak()
print(self.name + " makes a noise.")
end
end
- Classes are defined with
class Name ... end. - Inheritance:
class Dog : Animal ... end– the child inherits all methods. - Methods are defined with
fninside the class; they have an implicitselfparameter (the instance). - Constructor: a method named
initis called automatically when an instance is created. - Instantiation:
d <- Dog("Rex")calls the class as a function. - Method calls:
d.speak()– dot notation. - Field access:
self.name <- "..."– fields are stored directly in the instance.
8. Built‑in I/O
print(expr)— outputs the value ofexpr(converted to a string).input(prompt)— prints the prompt, reads a line from stdin, and returns it as a string.
9. First‑Class Types
The language treats types as data. type_of(10) returns the object int. You can compare it: if type_of(10) = int then ....
10. Importing
# Form 1: Import a module (file) – all definitions become available via a namespace import "math.flpl" result <- math.sqrt(16) # uses the 'math' namespace # Form 2: Import specific names from a module (bring them into the current scope) from "list_utils.flpl" import sort, reverse as rev my_list <- [3,1,2] sorted <- sort(my_list) rev_sorted <- rev(sorted) # Form 3: Import a built‑in module (like 'math' or 'io') without a file extension import math # looks for built‑in module named 'math'
- Module names are strings (with optional .flpl extension) or bare identifiers for built‑ins.
asrenaming is allowed for imported names.- Imported modules are cached – loading the same module twice returns the cached version.
11. Notable Syntactic Choices
| Feature | Syntax |
|---|---|
| Assignment | <-
|
| Equality | =
|
| Integer division | //
|
| Exponentiation | ^
|
| Comment | #
|
| Logical ops | and, or, not
|
| Multi‑line string | """ ... """
|
| Ordered pair | (first, second)
|
| Null | null
|
| Boolean literals | true, false
|
Example
Fibonacci
# Recursive Fibonacci with memoization
fn fib(n)
if n = 0 then
return 0
elseif n = 1 then
return 1
else
return fib(n - 1) + fib(n - 2)
end
end
print("Recursive fib(10) = " + to_str(fib(10))) # 55
# Iterative version (more efficient)
fn fib_iter(n)
a <- 0
b <- 1
if n = 0 then return a end
if n = 1 then return b end
i <- 2
while i <= n do
temp <- a + b
a <- b
b <- temp
i <- i + 1
end
return b
end
print("Iterative fib(10) = " + to_str(fib_iter(10))) # 55
Prime Number Detector
# Check if a number is prime
fn is_prime(n)
if n < 2 then
return false
end
i <- 2
limit <- n ^ 0.5 # sqrt via exponent 0.5
while i <= limit do
if n // i * i = n then # integer division and multiplication check
return false
end
i <- i + 1
end
return true
end
# Print all primes up to 50
print("Primes up to 50:")
i <- 2
while i <= 50 do
if is_prime(i) then
print(i)
end
i <- i + 1
end
Euclidean GCD
# Greatest Common Divisor using Euclid's algorithm
fn gcd(a, b)
remainder <- a % b
while b != 0 do
a <- b
b <- remainder
remainder <- a % b
end
return a
end
print("GCD of 48 and 18 = " + to_str(gcd(48, 18))) # 6