Crowbar

From Esolang
Jump to navigation Jump to search

Crowbar is an experimental programming language by User:nddrylliog that borrows some of the ooc syntax, adding rules which allow the implementation of low-level stuff from a high-level point of view.

Function syntax

 name: func (arg1, arg2, ...) -> ReturnType {
   // body
 }

The -> ReturnType part is optional.

So is the (arg1, arg2, ...) part.

Closure syntax

 callTwice: func (f: Func(Int)) {
   f(1)
   f(2)
 }
 
 callTwice(|x| x toString() println())

Generics

 Container: class [Elem] {
   elem: Elem
 }
 
 c: Container[Int]
 c elem = 42
 
 c2: Container[String]
 c2 elem = "Blah"

Rules

A simple rule

 fac: func (i: Number) -> Number {
   rule i > 0
   if(i > 1) i * fac(i - 1) else 1
 }

Quantifiers

 \A (decl | condition) = universal quantifier (ie. "for all <decl> such that <condition>")
 \E (decl | condition) = existential quantifier (ie. "there exists <decl> such that <condition>")

The | condition part is optional.

Sub-typing with rules (ie. narrowing types)

 Nat: cover from Number {
   rule \A (a: Nat | a >= 0)
 }

Alternative, shorter form:

 Nat: cover from Number {
   rule this >= 0
 }

Nested types

 Array: class {
   size: Nat
   
   Index: cover from Nat {
     rule this < size
   }
   
   get: func (i: Index) -> Elem
   
   // ...
 }

Examples

Incomplete code examples, more to come later:

 // Function syntax
 add := func (a, b) { a + b }
 add(3, 5)
 
 // Rule syntax!
 rule add(-a, b) == add(b, -a)
 
 // Covers can be re-used to create subtypes
 Nat: cover from Int {
   rule this >= 0
 }
 
 // Example of array data structure
 Array: class [Elem] {
   
   // Can't have a negative size, can have zero size
   size: Nat
   
   // dependent types
   Index: cover from Nat {
     rule this < size
   }
   
   // get	
   rule \A (i: Index)
     \E (e: Elem | get(i) = e)
   
   // add
   rule \A (i: Index, e: Elem)
     add(i, e) get(j) = match j {
       case j < i 		    => get(j)
       case j = i 		    => e
       case j < size + 1 => get(j - 1)
     }
    
   // append
   add(e) = add(e, size)
     
   // delete
   rule \A (i: Index)
     delete(i) get(j) = match j {
       case j < i 		    => get(j)
       case j < size - 1 => get(j + 1)
   }
 
 }
 
 List: class [Elem] {
   head, tail: Node
   
   Node: class {
     elem: Elem
     next, prev: Option[This]
     
     rule next prev = this
     rule prev next = this
     rule !\E head prev
     rule !\E tail next
     
     rule \A (e: Elem)
       add()
   }
 }