Skip to content

chadsec1/HolyLang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

500 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HolyLang

Unit Tests CodeQL Codacy Badge Codacy Badge

HolyLang programming language: Rust's compile-time safety, with Golang's readability.

HolyLang features:

  • HolyLang is more secure than Rust, but not as performant as Rust. The purpose of HolyLang is divine security, not speed.
  • HolyLang has readable syntax, and semantics.
  • HolyLang has no borrow checker, and yet is still more secure than Rust. programs can be easily reasoned about due to the simple binary safey model of "move, or copy".
  • HolyLang arithmetic is always checked, including bitwise. Floating point arithmetic is also always checked.
  • HolyLang has no warnings, only errors. Unreachable code? Error. Unused variable? Error. Etc.
  • HolyLang forces documentation for functions, structs, and constants.
  • HolyLang has no type inference, everything must be explicilty stated.
  • HolyLang does not allow overshadowing at all. Making codebases look cleaner, and reducing likelyhood of logic bugs.
  • HolyLang lock and unlock statements allow you to declare "zones" where variables behave as constants, dynamically.
  • HolyLang's bootstrap compiler transpiles down to pure Rust for a mathematical guarantee of safety: "If Rust is safe, then HolyLang must also be at least as safe as Rust".

.. and a lot more! This is just the bootstrap compiler, the actual compiler will have even more security features, such as static stack analyzes that guarantee (at compile-time!) a program cannot overflow the stack, allowing for even stricter security than Rust, and even other formally verified languages like Ada SPARK, whom have no stack overflow protection.

Work-in-progress

This bootstrap compiler implements parser, semantic analysis and enforcement, and the transpiler (transpiler still WIP). It still lacks: char types, structs, enums, sin (unsafe) blocks.

Compiling the bootstrap compiler.

Note: The latest commit in main branch is always the latest stable release.

  1. Clone the repository:
    git clone https://github.com/chadsec1/HolyLang.git
  2. Compile the compiler:
    cargo build --release

The compiler binary will be located in target/release/holylang. Feel free to move it wherever you like.

Compiling a HolyLang program

./holylang HOLY_SOURCE_CODE_PATH.holy TARGET_BINARY_PATH

That will compile a HolyLang file, and produce a binary at TARGET_BINARY_PATH.

Example syntax

# This is a comment


# `const` is the constant declaration keyword
# Constant declaration syntax is:
# const CONST_NAME CONST_TYPE = EXPRESSION
#
const hi int32 = 123

# A constant can have complex expressions in it, as long as it consists of literals 
# .. and or other constants.
#
const hey int32 = hi + 1 # That would be 124


func main() {
    # You can also declare constants within a scope
    # Like, this constant scope makes it only available within `main` function
    const idk int32 = hi * hey

    # `own` is the variable declaration keyword
    # Declaration syntax is:
    # own VAR_NAME VAR_TYPE = EXPRESSION
    #

    own x int32 = 1

    # Assignment example
    x = 2


    # Variable overshadowing is not allowed.
    # own x int64 = 2 # This would've been a compile-time error if I uncomment it.

    # Dynamic heap-allocated arrays example
    own arr []int32 = [1, 2, 3, 4, 5]

    # Fixed-size stack-allocated arrays example
    own fixed_arr [5]int32 = [1, 2, 3, 4, 5]

    # Nested dynamic arrays example
    own nested_arr [][]int32 = [[1,2], [3,4], [5,6]]


    # Nested fixed arrays example
    own nested_fixed [3][2]int32 = [[1,2], [3,4], [5,6]]


    # Array access example (array accessing is always a copy)
    own first_element int32 = arr[0] # This is equal to 1st element in array `arr`, which is 1

    # Array slicing example (array slicing is always a copy)
    own arr_slice []int32 = arr[1:3] # this creates new array starting from `arr`s 2nd element up to 4th element


    # Example of the move-or-copy safety model, where there is only one owner of a variable,
    # Holylang does not support references, borrowing, aliases, etc.
    # You either move a variable, or copy it.
    #

    own a int32 = 1
    own b int32 = x

    # This is invalid, it would not compile if I uncomment it.
    # a = 2

    own c int32 = copy(b)
    # This is valid, because `c` did not move `b`, it only copied it.
    b = 3


    # All basic primitive types have a default value:
    # 0 for integers, 0.0 for floats, false for booleans, 
    # empty arrays for arrays, "" for strings.
    #
    # The only exception to this rule are constants and fixed arrays.
    #
    own h int32
    # h has value of 0


    # Function calls example
    own res int32 = add(1, 2)


    # This is multi declaration
    own n1 int32, n2 int32, n3 int32 = give_3_numbers()

    # You can also do multi assignment
    n1, n2, n3 = give_3_numbers()


    # Strings example
    own name string = "John"

    # Format takes one string argument, placeholders are directly in string
    # To escape a placeholder use {{}}
    own greeting_str string = format("Hello, {name}! How are you ?")



    own v int32 = 1

    # Variable locking prevents assigning to it.
    # You can still move or copy it though.
    lock v

    # v = 2 # If I uncomment this, it will be compiler error


    # You can unlock variables.
    unlock v

    # Now these work fine!
    v = 2


    # If statements example
    own one int32 = 1
    own two int32 = 2

    if two > one {
        one = 2
    }

    if (one >= two) and (two <= one) {
        two = 6
    } elif (two > one) or (one < two) {
        one = 6
    } else {
        one = two * 2
    }


    # While loops
    while true {
        if one >= 100 {
            break
        } else {
            one = one + 1
        }
    }



    # For loops

    own names []string = ["john", "jane", "jack", "jeffrey", "epstein"]
    for s in names {
        if s == "jack" {
            break
        }
    }


    for i in range(1, 10) {
        if i == 7 {
            continue
        }
    }



    # Infinite loops
    own num int32
    infinite {
        # When you use variables in binary expressions, they are copied automatically, you dont need copy().
        num = add(num + 1, num + 2)


        if num >= 1000 {
            break
        }
    }

}


# Function that adds 2 numbers together and returns result
func add(a int32, b int32) int32 {
    own result int32 = a + b
    return result
}


# Function that returns 3 numbers
func give_3_numbers() (int32, int32, int32) {
    own a int32 = 1
    own b int32 = 2
    own c int32 = 3

    return a, b, c
}

Releases

No releases published

Packages

 
 
 

Contributors

Languages