Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

179 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

C Crispy

Work in Progress! The official C implementation of the Crispy Programming Language.

Crispy is a dynamically typed minimalistic scripting language. This implementation includes a bytecode compiler and a simple stack based virtual machine.

Take a look at some of the expamples in res/test/ to get an idea.

A slightly more advanced (but way slower) version of crispy can be found here: https://github.com/crispyteam/crispy-lang

Table of Contents

Just clone the repository and use CMake to generate the make files.

git clone https://github.com/funkschy/crispy
cd crispy
cmake .
make
./crispy

This will open an interactive shell where you can test the language very easily. Alternatively you can just save your code into a file and run:

./crispy [your filename]

If you decide to use the shell I would recommend wrapping the session with rlwrap.

If you don't have cmake installed you can also compile crispy like this:

gcc src/*/*.c -lm -o crispy

Crispy is tested with gcc/mingw and clang.

If you like to use vim (I like you already), you can use syntax highlighting. Just cd into the etc/vim/ directory and run the install script. It will simply copy the files you need to their positions.

1. Keywords

Crispy currently has only 13 keywords, even though more will follow, as the development process advances.

var

The var keyword is used to declare reassignable variables.

var greeting = "Hello World"
greeting = "How are you?"

val

'val' works just like 'var' with the small difference, that variables which are declared using 'val' keyword (these variables are called values) cannot be reassigned.

val greeting = "Hello World"
// this will cause an error
greeting = "How are you?"

nil, true & false

'nil' is Crispys version of a null value. 'true' and 'false' work just like they would in other languages.

println(1 == 1) // prints true

if & else

The 'if' and 'else' keywords works just like you would expect. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want (please don't ;) ).

if 1 < 2 {
println("this will be printed")
} else if 1 == 1 {
println("this won't")
} else {
println("this won't either")
}

However, in Crispy, every if-block is an expression (just like any other block except for while-blocks), so you can actually assign it to a variable.

val result = if true {
1 + 1
"Hello"
}
println(result) // prints "Hello"

if no block is executed, the result will be 'nil'.

while

The 'while' keyword works exactly the same way as in every other C based language. The only difference is, that you dont have to put the condition in parentheses (even though you can, if you want).

// prints 0 - 9
var i = 0
while i < 10 {
println(i++)
}

for

'for' loops work just as in any other C-based language.

for var i = 0; i < 10; i++ {
println(i)
}
// you can use the len() function to iterate over lists
val list = [1, 2, 3]
for var i = 0; i < len(list); i++ {
println(list[i])
}

fun

The 'fun' keyword can be used to declare user defined functions. All functions in Crispy are anonymous functions, so called lambdas. That means that most of the time you will simply assign the declared lambda to a variable or pass it as a parameter to another function.

val greet = fun -> println("Hello World")

After the fun keyword you can declare as many parameters as you wish. The paramter list is followed by the '->' operator, after which you can declare a single expression.

val add = fun a, b -> a + b
println(add(1, 2)) // prints 3

Since blocks in crispy are expressions, the lambda body can have an arbitrary length.

// of course you could just write ... -> a + b + c
// you could also just remove the return keyword, since the last expression in the block
// will be the return value
val add_3 = fun a, b, c -> {
val temp = a + b
val result = temp + c
return result
}
var result = add_3(1, 2, 3)
println(result) // prints 6

You can use any expression as a lambda body

val fib = fun n -> if n < 2 {
n
} else {
fib(n - 2) + fib(n - 1)
}
println(fib(20)) // prints 6765 

As you can see, recursion works aswell.

1. Compilation

The first part of running any Crispy program is the compilation. During this phase, the source code is broken down into its individual pieces (Tokens). Since Crispy only needs a lookahead of one Token, the source code is actually scanned one Token at a time. The compiler uses recursive descent parsing to convert complex productions into simple bytecode instructions. These bytecode instructions then get interpreted by a simple RISC virtual processor. The compiler is also responsible for initialising any constants found in the code. This means that strings are actually initialised (and interned) during compilation.

About

The official C implementation of the Crispy Programming Language (WIP!)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages