Skip to content
This repository has been archived by the owner on Aug 28, 2022. It is now read-only.

Compiles Closed-Form Script to a Facer compatible closed-form expression

License

Notifications You must be signed in to change notification settings

killerkalamari/cfs-compiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cfs-compiler

Compiles Closed-Form Script (cfs) to a closed-form expression fully compatible with the Facer Android Wear watchface composer tool and app. My goals for cfs are to facilitate the creation of watchface complications and secondarily to work around bugs and omissions in the Facer implementation. Using cfs, expressions can be generated that would be much too tedious to code by hand.

The cfs language provides additional functions for trigonometric and integer operations, const-style expression assignments, custom function declarations, and binary, ternary, and logical operators that are not based on the Facer equivalents.

The cfs.py compiler is written in Python and is compatible with both Python 2 and 3.

Table of Contents

Language Description

Operator Precedence

Internal Functions

Grammar

Language Description

Overall Structure

A cfs program is comprised of one or more lines of comments, function declarations, const assignment statements, and return expressions. No special statement terminator characters are necessary, although a semicolon may be used if desired. There must be at least one function defined, named main, that takes no arguments and returns an expression. The main() function is the starting point for program execution.

Comments

Single line and multi-line comments are available, using the familiar C/C++ operators, // and /* */. Comments may start at the beginning or end of a line. Multi-line comments may span multiple lines and end in the middle of a line, if desired.

Single line comment examples:

//return atan2d(0.559666, -0.762512)
lat = 37 // Latitude for North America 

Multi-line comment example:

/*
function jupiter()
	return planet(11.857911, 337.917132, 5.20278)
*/

Identifiers

Identifiers in cfs are used for function and const names, and are case sensitive. They are comprised of upper- and lowercase ASCII letters, numbers, and/or underscores, but cannot begin with a number.

Facer Constants, Operators, Tags, and Functions

Facer constants, operators, tags, and functions may be used, with their standard syntax. However, the Facer ternary and logical operators have been replaced.

Literals

Real numbers, pi, and e are supported as literals in cfs.

Data Types

Although all cfs values are represented by floating-point numbers, functions will only produce defined results when input values adhere to the following input type restrictions:

Type Description
float Floating-point (real) number
int Integer (whole) number
bool Boolean values 0 (false) and 1 (true)

Operators

The following operators are available in addition to the standard arithmetic operators. Some operators have restrictions on input values. Refer to the Internal Functions table for details.

Operator Syntax Input Types Output Type Description
! !x bool bool Boolean not.
not not x bool bool Boolean not.
^ x^y float, float float Exponentiation, left-associative. Tip: To square a number, use x * x.
% x%y float, float float Modulo (remainder) function.
<= x<=y int, int bool Integer less than or equal to.
>= x>=y int, int bool Integer greater than or equal to.
<: x<:y float, float bool Floating-point less than.
>: x>:y float, float bool Floating-point greater than.
< x<y int, int bool Integer less than.
> x>y int, int bool Integer greater than.
== x==y int, int bool Integer equality.
= x=y int, int bool Integer equality.
!= x!=y int, int bool Integer inequality.
<> x<>y int, int bool Integer inequality.
&& x&&y bool, bool bool Boolean and.
and x and y bool, bool bool Boolean and.
` ` `x
or x or y bool, bool bool Boolean or.
if(,) if(b,t) bool, float float Binary operator. Returns t on true, 0 on false.
if(,,) if(b,t,f) bool, float, float float Ternary operator. Returns t on true, f on false.

Consts

A const defines a name for an expression, with scope restricted to the function in which it is defined. Consts may not be redefined within a function, however the same const name may be defined in multiple functions.

Function Definitions

Functions in cfs may have zero or more required parameters, surrounded by required parentheses. Parameters may be optionally comma-separated. Functions may include zero or more statements, and must conclude with one return statement.

Statements

Assignment Statement

Assigns an expression to a const. The const name and expression must be separated by =.

Return Statement

Defines the return expression of a function.

Operator Precedence

Precedence Operators Description
1 (), fn() parentheses, function calls
2 -, !, not unary minus, bool not
3 ^ exponentiation
4 *, /, % multiplication, truncating division, division, modulo
5 +, - addition, subtraction
6 <=, >=, <:, >:, <, > int and float comparisons
7 ==, =, !=, <> int comparisons
8 &&, and bool and
9 `
10 if(?), if(?:) binary and ternary conditionals

Internal Functions and Operators

Function Input Types Output Type Implementation Domain
acosd(x) float float deg(acos(x)) −1 ≤ x ≤ 1
asind(x) float float deg(asin(x)) −1 ≤ x ≤ 1
atan2(y, x) float, float float atan(y / x) + (x <: 0) * signf(y) * pi x ≠ 0, y ≠ 0
atan2d(y, x) float, float float deg(atan2(y, x)) x ≠ 0, y ≠ 0
atand(x) float float deg(atan(x))
cosd(θ) float float cos(rad(θ))
int(x) float int floor(x) + (1 - sign(floor(x))) / 2
sind(θ) float float sin(rad(θ))
sign(i) int int signf(i + 0.5) x ≠ -0.5
signf(x) float int abs(x) / x x ≠ 0
signn(i) int int signf(i - 0.5) x ≠ 0.5
tand(θ) float float tan(rad(θ)) x ≠ π/2 + kπ
!x, not x bool bool 1 - x x = [0, 1]
x ^ y float, float float exp(log(x) * y) x ≠ 0
x % y float, float float x - (y * floor(x / y)) y ≠ 0
x < y int, int bool (1 - sign(x - y)) / 2 x - y ≠ -0.5
x <= y int, int bool (1 - signn(x - y)) / 2 x - y ≠ 0.5
x > y int, int bool (1 + signn(x - y)) / 2 x - y ≠ 0.5
x >= y int, int bool (1 + sign(x - y)) / 2 x - y ≠ -0.5
x <: y float, float bool (1 - signf(x - y)) / 2 x - y ≠ 0
x >: y float, float bool (1 + signf(x - y)) / 2 x - y ≠ 0
x == y, x = y int, int bool (x >= y) * (x <= y) x - y ≠ ±0.5
x != y, x <> y int, int bool (4 - (1+sign(x-y)) * (1-signn(x-y))) / 4 x - y ≠ ±0.5
x && y, x and y bool, bool bool x * y x, y = [0, 1]
`x y, x or y` bool, bool bool
if(b ? t : f) bool, float, float float b * (t - f) + f
if(b ? t) bool, float float b * t

Formal Grammar

program =
    function { function }
    ;

function =
    [ "function" | "def" | "double" ] ID "(" [ ID { [ "," ] ID } ] ")" [ ":" | "{" ]
        { statement [ ";" ] }
        "return" expression [ ";" ]
        [ "}" ]
    ;

statement =
    ID "=" expression
    ;

expression =
    "if" "(" expression ( "?" | "," ) expression [ ( ":" | "," ) expression ] ")"
    | or_expression
    ;

or_expression =
    and_expression { ( "||" | "or" ) and_expression }
    ;

and_expression =
    equ_expression { ( "&&" | "and" ) equ_expression }
    ;

equ_expression =
    rel_expression { ( "==" | "=" | "!=" | "<>" ) rel_expression }
    ;

rel_expression =
    add_expression { ( "<=" | ">=" | "<:" | ">:" | "<" | ">" ) add_expression }
    ;

add_expression =
    mult_expression { ( "+" | "-" ) mult_expression }
    ;

mult_expression =
    exp_expression { ( "*" | "/" | "%" ) exp_expression }
    ;

exp_expression =
    unary_expression { "^" unary_expression }
    ;

unary_expression =
    "-" primary_expression
    | ( "!" | "not" ) primary_expression
    | primary_expression
    ;

primary_expression =
    "(" expression ")"
    | ID [ "(" [ expression { [ "," ] expression } ] ")" ]
    | NUM
    | TAG
    ;

About

Compiles Closed-Form Script to a Facer compatible closed-form expression

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published