Giter VIP home page Giter VIP logo

fup's Introduction

FUP - Fuck Un(losed Parens

FUP is a preprocessor for Scheme programming language. It is intended to help avoid the overuse of parens in Scheme in situations when even rainbow colorizers stop helping.

FUP uses pest.rs to parse Scheme and augmented expression. Augmented expressions are then converted to Scheme and valid Scheme code is output.

Usage

The binary currently has two modes - file and repl.

To start the repl, run the binary with no arguments. To read input from file, start the binary with the first cli argument set to the file path.

Currenty, repl has the following meta commands:

Command Description
,exit Exits the repl
,help Prints help with these commands
,mline Toggles multiline and immediate evaluation

Note: By default, repl runs in multiline mode, which means input is buffered until an empty newline is passed.

FUP expressions

Currently, FUP supports these augmented expressions:

Define

Helps the readability of define statements:

define foo(x, y) {
	(display (+ x y))
}
define bar = z;

becomes

(define
	(foo x y)
	(display (+ x y))
)
(define bar z)

Let

Similar to define, helps with readability:

let x = 1 {
	(display x)
}
let* x = foo(1,), y = x {
	y
}

; Can also be implicitly scoped
define foo(x, y) {
	let z = x + y
	(display z)
}

becomes

(let
	(
		(x 1)
	)
	(display x)
)
(let*
	(
		(x (foo 1))
		(y x)
	)
	y
)
(define
	(foo x y)
	(let
		(
			(z (+ x y))
		)
		(display z)
	)
)

Function call

Functions are called in the same way as they are defined:

foo(x, y)

becomes

(foo x y)

However, calling functions with one or zero arguments has a caveat to avoid ambiguity with natural scheme code:

foo (x) ; not a call
foo (x,) ; unambiguous call
foo(,) ; unambiguous call, no arguments
(lambda (x) x)(1,) ; scheme expression call
{ cond {
	#f => foo,
	#t => bar
} }(1,) ; fup expression call

becomes

foo (x) ; not a call
(foo x) ; unambiguous call
(foo) ; unambiguous call, no arguments
((lambda (x) x) 1) ; scheme expression call
(
	(cond
		(#f foo)
		(#t bar)
	) 1
) ; fup expression call

Cond

Cond works similar to switch statemets or the Rust match statement:

cond {
	a => b,
	c => d,
	x => y,
	else => z
}

becomes

(cond
	(a b)
	(c d)
	(x y)
	(else z)
)

List indexing

Lists can be indexed to avoid nested cars and cdrs from making list accesses unreadable:

lst[1] ; one element index
lst[2..] ; slice-after index
lst[..2] ; slice before index
lst[1..1] ; slice between index, empty
lst[1..3] ; slice between index
(list 1 2)[1] ; scheme expression index
{ foo(,) }[0] ; fup expression index

becomes

(car (cdr lst)) ; one element index
(cdr (cdr lst)) ; slice-after index
(list
	(car lst)
	(car (cdr lst))
) ; slice before index
() ; slice between index, empty
(
	list
	(car (cdr lst))
	(car (cdr (cdr lst)))
) ; slice between index
(
	car (cdr (list 1 2))
) ; scheme expression index
(
	car (foo)
) ; fup expression index

Note: Be aware that the ..N and N..M variations evaluate the indexed expression as many times as the the length of the resulting list.

List literal syntax

Lists can be created using [item, item, ..] syntax.

[1,2,3]
[1,2,3,]
[]              ; useful as '()
( foo [1,2] )
( foo [1,2,] )
( foo [1,] )    ; trailing coma disambiguates list literal
( foo [1] )     ; indexing into foo has precedence
( foo [] )      ; with no argument list wins again
{[1,2,3]}[1]    ; indexing possible when wrapped in {}

becomes

(list 1 2 3)
(list 1 2 3)
(list)          ; results in the same thing as '()
(foo (list 1 2))
(foo (list 1 2))
(foo (list 1))
((car (cdr foo)))
(foo (list))
(car (cdr (list 1 2 3)))

Binary operator infixing

Binary operators can be infixed as in other langauges:

1 + 2

a == b ; "==" is an alias for "equal?"

#t is #t ; "is" is an alias for "eq?"

becomes

(+ 1 2)

(equal? a b)

(eq? #t #t)

Note: To avoid ambiguity, infixed operators only work in non-scheme contexts.

Escaping

Some FUP expressions (such as infixed operators) can be ambiguous in Scheme contexts. To explicitly create a FUP context and parse expressions as FUP expressions, use {} blocks:

(define
	(foo x y)
	{x + y}
)

becomes

(define
	(foo x y)
	(+ x y)
)

fup's People

Contributors

theedward162 avatar

Watchers

 avatar  avatar

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.