Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

The malang programming language

License

NotificationsYou must be signed in to change notification settings

traplol/malang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

First and foremost, this is just a place for me to try things and to learn about how one might implementa programming language.

malang is a general purpose, statically and strongly typed, structured programming language. It is earlyin development but already it features:

  • a tracing garbage collector
  • type inference
  • primitive types such asstring,int,bool,double,buffers, and arrays.
  • first class function expressions
  • block expressions
  • bound/named functions that support parameter overloading
  • extend any type with operators and methods
  • user-defined structures
  • strong type aliasing
  • a file-based module system

Planned features:

  • multiple return values
  • string interpolation
  • closures
  • zero overhead generics
  • traits
  • exceptions
  • optimized ahead of time compiliation that can be saved to disk and run at a later time.

malang is compiled into a fairly low-level stack-based bytecode which is then interpreted by the malangVM.

Building

There are plans to support and move towards CMake, buttup is the current build tool.

Building on *nix

  1. Make sure you have installed the dependencies:
  • g++ 4.7 or later orclang++ 3.x or later
  • tup
  • git
  1. Build and run
$ git clone https://github.com/traplol/malang$cd malang$ tup init$ tup$ ./mal -q examples/hello-world.ma  hello world!

Crash course

Variables

Variables can be declared with their type, or the type may be entirely omitted if it can be immediately deduced.

x : intx = 42y : double = 123.45PI := 3.14159PI = 3.0             # compile error because ALL_CAPS signifies it is a constantz := "hello world"a : int = 1.5        # compile error without explicit castb := returns_int()c := if true "yep" else "nope"

Flow control

An if/else block may be used as a value if the last expression for both legs is notvoid

# `and` and `&&` are the same and `or` and `||` are also the sameif one    println("hello world")else if two or three and four    println("wat")else if five || size && seven    println("woo!")else    println("hmm")x := if get_condition() "yes!" else "nope"

While loop

# poor man's for loopi := 0while i < n {    do_thing(i)    i += 1}

For loops expect the thing being iterated to implementfn current() -> T andfn move_next() -> bool wherefn move_next() -> bool returnsfalse when there are no more iterations left. Seerange.mafor a trivial Range implementation

for Range(0, 10) {    println(it) # `it'em is implied}# You may also name the item with the `for ident in ...` syntaxfor i in Range(0, 10) {    for j in Range(10, 20) {        println(i * j)    }}

Functions

Functions can be defined and bound to a name, assigned to a variable, or used as a value in an expression. Themain difference between binding to a name and to a variable is a function bound to a name can share that namewith other bound functions if their parameter types differ.

SeeBUILTINS for a list of builtin and always availble functions.

# Binds to 'hello' with with no parametersfn hello() -> void {    println("hello world")}# Binds to 'hello' with 1 parameter (int)# notice the void return type has been ommitted/impliedfn hello(a: int) {    hello()    println(a)}min := fn(a: double, b: double) -> double {    if a < b        return a    else        return b}fib := fn(n: int) -> int {   if n < 3 {       return 1   }   else {       # notice the use of 'recurse' because otherwise 'fib' could be redefined to another        # function with the same function signature and that one would get called instead.       return recurse(n-1) + recurse(n-2)   }}

Arrays and buffers

Arrays consist of values/references andbuffers are blocks of memory with byte-index ganularity.Both are special because theirlength,[] and[]= properties are optimized into theirown respective malangVM instructions. Both are bounds checked but unchecked instructions do exist forwhen the compiler can be certain an index cannot possibly be out of range.

n := 123nums := [n]int  # dynamically allocate 123 uninitialized intsi := 0while i < nums.length {    nums[i] = i * i    i += 1}a_buf := buffer(128) # 128 byte bufferi = 0while i < a_buf.length {    a_buf[i] = i    i += 1}

User defined types

type D = {    e := 0        _private_var := "hello world"     # starts with _ so this is private in this context    CONST_VAR := 99                   # ALL_CAPS so this is constant/readonly in this context    public_var := true                # not _private or CONST to this is public    _ANOTHER_CONST := 111             # _private and CONST        new (e: int) {        self.e = e    }}# A, B, and C don't have a constructor that takes parameters so the default constrcutor# is implied. In the future, types will also be order independent.type C = {    d := D(42)}type B = {    c := C()}type A = {    b := B()}a := A()println(a.b.c.d.e)type Vec3 = {    x := 0.0    y := 0.0    z := 0.0    # default, only necessary because we define another constructor    new () {}      new (x: double, y: double, z: double) {        self.x = x        self.y = y        self.z = z    }    fn * (scalar: double) -> Vec3 {        # note the implicit resolution of x,y,z         return Vec3(x*scalar, y*scalar, z*scalar)    }    fn + (other: Vec3) -> Vec3 {        # and here we can shadow fields of the same name but still access them with        # the implicit "self" reference        x := self.x + other.x        y := self.y + other.y        z := self.z + other.z        return Vec3(x, y, z)    }    fn - (other: Vec3) -> Vec3 {        x := self.x - other.x        y := self.y - other.y        z := self.z - other.z        return Vec3(x, y, z)    }}a := Vec3() # creates a Vec3 with the default constructora.x = 999.0b := Vec3(1.5, 2.3, 3.14)c := a + bprintln(c.x) # 1000.5println(c.y) # 2.3println(c.z) # 3.14

Strong type aliasing

Type aliasing is a way to distinguish types which have the same internal representation from eachother without unnecessary runtime overhead. Type aliasing also allows you to write extensions foran aliased type separate from higher types and separate from any neighboring type aliases whileallowing these methods to be available to any sub-aliases.Seealias.ma for a more comprehensive example.

type alias cents   = inttype alias dollars = inttype alias time_ms = intfn cents(d: dollars) -> cents {    # `unalias' converts to the top type of an alias hierarchy: in this case `unalias(d)' is an `int'    return unalias(d) * 100}fn dollars(c: cents) -> dollars {    return unalias(c) / 100}money    : dollars = 45     # ok: 45pennies  := cents(money)    # ok: 4500duration : time_ms = 2750   # ok: 2750#bad1 : cents = duration    # compile error, no conversion exists#bad2 : dollars = duration  # compile error, no conversion existsok1   : dollars = 45         # 45 is an int which is the aliased typeok2   : cents = 9999         # 9999 is an int which is the aliased type#bad3 : cents = 42.69       # compile error, 42.69 is not an int

Extensions

Extensions allow you to implement new methods and operators on any existing type but they do notallow you to add more fields to them.

# string multiplication doesn't yet exist, so let us implement itextend string {    fn * (n: int) -> string {        # edge case        if n <= 0 {            return string(buffer(0))        }        total_len := self.length * n        tmp_buf := buffer(total_len)        i := 0        while n > 0 {            k := 0            while k < self.length {                tmp_buf[i] = self[k]                i += 1                k += 1            }            n -= 1        }        return string(tmp_buf, total_len)    }}println("hello " * 10) # hello hello hello hello hello hello hello hello hello hello

Releases

No releases published

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp