Alexander Tsepkov
Software developer, entrepreneur, and creator of RapydScript language.
Alexander Tsepkov
11/22/2016
What makes the current generation of compilers intelligent is the fact that they can infer information from
incomplete data.
Parser
Lexer
AST
Output
Input
Output
Parser
Lexer
AST
Output
Transformer
Linter
Optimizer
SourceMaps
REPL
Input
Output
Parser
Lexer
AST
Output
Splits text into tokens (words)
Combines tokens into nodes (sentences)
Abstract Syntax Tree (essay)
Prints AST back in new format (translator)
Some purists will separate transformer and output, I did not.
Sometimes you'll see tokenizer instead of lexer, they're similar.
Turns out more freedom is not always good
These are great for QA
But they all require setup, and in our tendency to find shortcuts we sometimes avoid them, especially with smaller projects.
Static typing occupies a niche somewhere between linting and unit tests. It will tell you if you're getting your apples and oranges mixed up, but it won't prevent you from shooting yourself in the foot.
// Flow example
function foo(num: number) {
if (num > 10) {
return 'cool';
}
}
console.log(foo(100).toString());
// error: `toString` cannot be called on possibly null valueIt's like a free unit test!
It lets us start off the project with loose checks and tighten them when we're ready, without the extra setup of other testing solutions.
That doesn't mean we shouldn't be relying on other mechanisms, just that it will be less dreadful to come back to our code when we can ensure at least some safety.
Recent Interview:
Hybrid typing drives us to better design
interface Vehicle {
wheels: number;
color: string;
passengers?: number;
move(x: number, y: number);
}
class Car implements Vehicle {
...
}
function isSafeToDrive(vehicle: Vehicle): boolean {
return vehicle.wheels > 1;
}function copyFields<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = source[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 }); // okay
copyFields(x, { Q: 90 }); // error: property 'Q' isn't declared in 'x'.a = {}
b = "test"
...
b() # Error: 'b' is not callable
c = a + b # Error: can't concatenate String and ObjectTypeScript:
window.onmousedown = function(mouseEvent) {
console.log(mouseEvent.buton); // Error: Window.onmousedown
}; // argument (MouseEvent) has
// no .butonRapydScript:
a = { foo: 1, bar: { baz: "qux" } }
b = { "foo": 1, bar: { baz: "qux" } }
c = 'foo'
d = 5
a == b # true, performs deep equality
a == c # false, optimized to ===
a == d # false, optimized to ===RapydScript uses a number of tricks to achieve proper deep-equality that JavaScript lacks without the overhead that a deep equality function would introduce.
function bar(c: string): string {
return c;
}
function foo(a) {
a = bar(a);
return a + "test";
}
foo([]);
# no errordef bar(c: String) -> String:
return c
def foo(a):
a = bar(a)
return a + "test"
foo([])
# Error: foo call triggers a callback to foo,
# which in turn triggers a callback to bar and
# resolves type at the time of the call itself
# rather than just at the time of declaration(Work-in-progress state manager for RapydScript)
def baz(a, b, c):
return a + b + c
baz(1, 2, 3) # 6
baz(1, 2, 3, 4) # error, signature mismatch
baz([], 2, 3) # error, array concatenation
baz('quick', c=' fox', b=' brown') # 'quick brown fox' (arg swap)(Work-in-progress state manager for RapydScript)
def foo(a: String or Num) -> String:
return "You passed " + a.toString()Parser
Lexer
AST
Output
Parser
Lexer
AST
Output
Finds tokens
Finds relationships between tokens
Parser
Lexer
Interstate
Finds tokens
Finds relationships between tokens (context)
Finds relationships between contexts
Parser
Lexer
Interstate
Finds tokens
y
y'
y''
Finds relationships between tokens (context)
Finds relationships between contexts
atsepkov@gmail.com
@atsepkov
github.com/atsepkov
By Alexander Tsepkov
Software developer, entrepreneur, and creator of RapydScript language.