Git Product home page Git Product logo

hlwnpa's Introduction

HLWNPA - Henry's Language With No Pronounceable Acronym

I started this project to see what I could acomplish in about a week's worth of work, without any prior knowledge about language design. What I got looked sort of like a programming language. I have since continued to work on this language, adding additional features it didn't have after the first week.

Process

I defined what the AST should look like, then defined a syntax that would parse input to that AST, and then implemented a REPL. I then proceeded to graft things onto the AST and syntax parser once I had a minimal language.

Features

  • Nothing to limit reassignment. If you want to assign a number to a function name, there is nothing stopping you.
  • No meaningful parser error messages. If your syntax isn't 100% accurate, there is very little to indicate what you did wrong. Sometimes the program will parse, but may leave out a section of the AST without errors if syntax isn't exact. The result is if you define a function incorrectly, that function will not exist, and you won't know until you try to call it.
  • A few runtime error messages.
  • No early return from functions. The last statement in the body of a function, if, loop block will be returned.
  • Type System. Runtime checking only.

Actual Features

  • REPL.
  • Primitive types: Number (signed 32 bit), Float (64 bit), String, Booleans, and Arrays (only containing primatives at the moment). As well as Structs.
  • Assignment: let value := 4 * 6.
  • Constants: const VALUE := 5.
  • Reassignment: value := 1.
  • While loops: while value < 100 { value + 1 }.
  • Arrays: let a := [0,1,2,3].
  • Array ranges: [0..3] produces an array [0,1,2].
  • Array access: a[2].
  • For loops: for n in [0..3] { println(n + "") }.
  • Functions:
fn function_name (parameter1: Number, parameter2: Float) -> Float { 
   parameter1 + parameter2 
}
  • Function execution: function_name(3, 1.3).
  • Structs:
struct struct_name {
   field1: Number, field2: Number
}
  • Struct instantiation
let instance := new struct_name {
   field1: 4, field2: 5
}
  • Struct access
instance.field1 + instance.field.2

Currently there is no association of functions with structs.

  • Includes in the form of include <filename>. The filename path is relative to where the interpreter is called from and requires the full file name (including .hlw).
  • Operator precedence.

Example Program

Program 1

let x := 5
fn add_2_to_number( number: Number) -> Number {
   number + 2 
}
add_2_to_number(x)

Returns: Number(7)

Program 2

struct MyStruct {
    a : Number
    b : Number
}

let a := 3

fn create_new_MyStruct( value: Number ) -> MyStruct {
    new MyStruct {
        a: 8
        b: value
    }
}

fn addContents( s: MyStruct ) -> Number {
    s.a + s.b
}

let instance := create_new_MyStruct( a )

addContents( instance )

Returns: Number(11)

TODO

  • Switch to using S-Expressions, where each operator holds one or more operators or literals. This would replace the current implementation that just has binary and unary expressions that hold the operator and its operands. S-Expressions are now used.
  • Since switching to S-Expressions, parentheses can't be used to control oreder of execution. Add optional parentheses to allow for this.
  • S-Expressions currently always evaluate from right to left, the parser should be able to organize the operations so that multiplication ocurrs before addition if given 3 * 3 + 1. That should result as 10, instead of 12. S-Expressions will be parsed left to right with operator precedence ( *, /, %) > ( +, -) > ( >=, <=, >, <) > (==, !=). A sub-expression can be wrapped in () and will evaluate first before continuing to the next operator and tokens.
  • S-Expression parsing with precedence is very slow. This is because the parser would try to match a LHS and an operator for every supported operator, before it found that only a single number or variable had to be parsed. Rewrote the S-Expression parser. Now only about 2x overhead over no precedence logic for simple programs versus the 100x or more for the prior parser.
  • && and || operators are not implemented yet. They should have the least precedence.
  • Introduce Floats.
  • Introduce mutability rules. const vs. let. Mutability now exists as a system that is enforced after the AST has been parsed, but before it is evaluated. This makes the time to enforce mutability rules proportional to the number of assignment related S-Expressions in the AST and doesn't crash the program at runtime.
  • Prevent reassignment of Struct and Function names. Currently, you are allowed to set the identifier for a struct's type to be a number, this has wonky consequences for the type system.
  • Investigate Nom's custom error messages.
  • Figure out how to display a line number for a parser error and highlight the part of syntax that failed.
  • Flesh out the runtime error messages, give them more data related to the error, and implement Display for them so they are printed out nicely when an error occurs.
  • When executing a file, hoist the functions and struct declarations, search for a main function, evaluate it if found, otherwise, evaluate AST nodes that exist outside of functions. If the file only contains functions and structs and no main function, throw an error. Hoisting and main() execution implemented.
  • Allow the REPL to read a file at startup and access its functions, structs, and variables. REPL after reading a file implemented.
  • Implement an Include <filename> keyword that will parse another file and load the other file's AST into the original files's AST. include <filename> will now move the AST of the specified file into the calling file's AST.
  • Possibly implement loop unrolling inside of functions, as well as precomputation of S-Expressions with literals. So code that looks like let a := 3 + 8 would be optimized to let a := 11 if it exists within a function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.