Impera – A New Programming Language
I’ve decided to take up the immense and intriguing task of designing a programming language. I expect that it will be quite difficult to do, as I have not taken a compiler or language design class, but I expect that MIT’s Design Concepts in Programming Languages ought to be a pretty good introduction to the topic. Luckily, I’m not starting completely from scratch- I do have some experience with C and Scheme (a type of Lisp).
I’ll build my language in the former, and the later has given me a view into a functional/metaprogramming language.
Goals
- Compiled (as fast as C), with the simplicity of interpreted like Python
- Extensible metaprogramming, like a lisp
- Ease of concurrent design, like Go
- Great Tooling
- Something like rust’s cargo (package manager, test runner, etc)
- Something like gofmt
- First class IDE support
General
- Inbuilt unicode support
- Literate programming (like Pluto notebooks for Julia)
- All objects are pass by reference, is everything else pass by reference, as well?
- Lexical, local scoping (like most normal langs)
- Interoperability with C?
Decisions to Make
- White Space EOF
- Comments
- single line: //
- multiline: /* */
- Typing
- Strong static type system (like Haskell)?
- Will string be implemented as an object, or a primitive?
- Garbage collection?
Syntax
Variable Declarations
- Variables names can only have alpha numerics and underscore
- Camelcase
let mut foo: i32 = 43
// immutable
let bar = "Hello World"
Data Types
i8
,i16
i32
,i64
f32
,f64
bool
'char'
,"string"
complex
(maybe not needed)No implicit casting
Operators
- Chaining like
3 < x < 7
is allowed
- Chaining like
Functions
- Declaration
fn swap(a: str, b: str) -> (str, str) {
return b, a
}
- Can return nothing
fn increment(num: i32) {
num++
}
- Closures
let a = num1::i32, num2::i32 {
num1 + num2
}
Data Sructures
- Array, Vector, List (Dynamic Array basically), Tuple, Dictionary/HashMap, Set, Trees, Stringbuffer
var books = HashMap::new()
books.insert("A Tale of Two Cities", "C. Dickens")
or
var books = new HashMap()
books.insert("A Tale of Two Cities", "C. Dickens")
- De-structuring/unpacking
Flow Control
- Ternary
let mut x: i32
let mut y: i32
// choose one of these
x = x > 10 ? x : 10
y = y if y > 10 else 10
- For loop (or do the normal for loop without all these random complications)
const people = ["Dickens", "Berkley", "Pauling"]
for person in people {
println!(person)
}
for i in 2..22 {
println!(i)
}
// -> 2, 4, 6, 8, 10, ..., 22
for i in 1..11:2 {
println!(i)
}
// -> 1, 3, 5, 7, 9, 11
- While loop
while 5 < x < 10 {
println!(x)
x += 1
}
- If, else if, else
if x < 10 {
print!("{} is less than 10", x)
} else if x == 10 {
print!("{} is equal to 10", x)
} else {
print!("{} is more than 10", x)
}
- Match Statement
const number = 4
const msg = match number {
// Match a single value
1 => "One!",
// Match several values
2 | 3 | 5 | 7 | 11 => "This is a prime",
// Match an inclusive range
13..=19 => "A teen",
// Handle the rest of cases
_ => "Ain't special",
}
println!(msg)
Important (TODO)
- Pointers
- Functional
- Tries
- Lambdas (needs work)
fn function (i: i32) -> i32 { i + 1 }
- Metaprogramming
- Macros
- Metaclasses?
Organize
- OOP? -> Messaging
- Inheritance
- Structs
struct pair {
var x: i32
var y: i32
}
struct pair p
p.x = 4
p.y = 10
Option
- No nulls
Enums / Algebraic Data Types
enum Shape {
Square,
Triangle,
Square
}
- Some and None
- Imports
use impera::utils::Io as io
- Access modifiers
- public:
pub
- private to module:
priv
- private to file (protected):
pro
- public:
// in src/lang/main.imp
priv const foo = "I love Languages!"
// in src/main/main.imp
println!(foo) // => does not have access *error*
I’ll be periodically detailing my journey with the creation of this language in this blog.