Funky

From Esolang
Jump to navigation Jump to search

Introduction

Funky, a function-based language! It is an esolang where you can't do anything other than creating and executing functions (but I guess you can because its Javascript). The syntax is completely just Node.js's syntax (mainly because I am very lazy).

Functions

There are some pre-made functions in Funky... a lot of them. And they are:

  • println(v) ---------------------------------- prints 'v' with a newline
  • print(v) ------------------------------------ prints 'v'
  • setVar(varName, varValue) ------------------- sets the variable 'varName' to 'varValue'
  • getVar(varName) ----------------------------- returns the contents of the variable 'varName'
  • incVar(varName) ----------------------------- varName++
  • decVar(varName) ----------------------------- varName--
  • loop(start, end, step, callback) ------------ basically a for-loop --- for (let i = start; i < end; i += step) {callback}
  • length(array) ------------------------------- returns the length of an array 'array'
  • push(varName, value) ------------------------ push 'value' into 'varName'
  • pop(varName) -------------------------------- pop 'varName' and return it
  • shift(varName) ------------------------------ shift 'varName'
  • unshift(varName) ---------------------------- unshift 'varName'
  • assert(condition, callback, fallback) ------- literally an if statement made into a function
  • input(varName) ------------------------------ gets input and stores into 'varName' (needs to be called in an await way)
  • exit(code) ---------------------------------- exit with code 'code'
  • tryCatch(try, catch) ------------------------ try to execute 'try' or execute catch(e) if failed (e=errorMessage)
  • readFile(file, varName) --------------------- works like input
  • writeFile(file, data) ----------------------- over-write file with data
  • randomInt(min, max) ------------------------- return a random integer with bounds of 'min' to 'max'
  • randomFloat(min, max) ----------------------- works like randomInt
  • randomString(len) --------------------------- random string with 'len' amount of characters
  • randomItemOfArray(array) -------------------- select random item of array 'array'
  • getCurrentTime() ---------------------------- get current time
  • threeLettersBack(string) -------------------- encrypt 'string'
  • threeLettersForward(string) ----------------- decrypt 'string'

Phew... thats a lot of functions!

Examples

Now, a normal program doing nothing would look something like this:

 (async () => {
   exit(0)
 })()

and here are two examples:

Hello World

 (async () => {
   println("Hello World")
   exit(0)
 })()

truth-machine

 (async () => {
     await input("x")
     assert(getVar("x") === "1", () => {
         loop(0, Infinity, 1, () => {
             print("1") // Print 1 for the rest of eternity
         })
     }, () => {
         assert(getVar("x") === "0", () => {
             println("0")
         })
     })
     exit(0)
 })()

Creating custom functions

So, you just made some of your programs and want to make more functions than Funky offers you (if so, ISN'T THAT ENOUGH???).
Well, You are in the right place, functions are basically variables. So this is how you can do it:

 setVar("Function Name", (parameters) => {
   return (parameter + parameter * 4) - 4
 })

Done! You have just created a function... but you don't know how to run it. No problemo!

 setVar("x", getVar("Function Name")(10))

Here, 10 is the parameter. And because of the return (Why is the return keyword not a function??) the result gets passed into the variable "x"

Implementation (in Node.js)

And heres the implementation (2 files):

(index.js)

 const fs = require('fs')
 const vm = require('vm')
 const readline = require('readline')
 const context = {
   console: console,
   readline: readline,
   process: process,
   fs: fs
 }
 const defenitionsCode = fs.readFileSync('defenitions.js', 'utf8')
 vm.runInNewContext(defenitionsCode, context)
 const funkyCode = fs.readFileSync(process.argv[2], 'utf8')
 vm.runInNewContext(funkyCode, context)

(defenitions.js)

 // Initialize
 const rl = readline.createInterface({
   input: process.stdin,
   output: process.stdout
 })
 const vars = {}
 // Variable related functions
 function println(value) {
   console.log(value)
 }
 function print(value) {
   process.stdout.write(value)
 }
 function setVar(name="x", value) {
   vars[name] = value
 }
 function getVar(name="x") {
   return vars[name]
 }
 function incVar(name="x") {
   setVar(name, getVar(name) + 1)
 }
 function decVar(name="x") {
   setVar(name, getVar(name) - 1)
 }
 // Loop
 function loop(start=0, end=10, step=1, callback=()=>{println("You forgot")}) {
   if (step > 0) {
     for (let i = start; i < end; i += step) {
       callback(i)
     }
   } else if (step < 0) {
     for (let i = start; i > end; i += step) {
       callback(i)
     }
   }
 }
 // Array functions
 function length(array=["You", "forgot", "to", "give", "an", "argument"]) {
   return array.length
 }
 function push(name="x", value) {
   getVar(name).push(value)
 }
 function pop(name="x") {
   return getVar(name).pop()
 }
 function shift(name="x") {
   return getVar(name).shift()
 }
 function unshift(name="x", value) {
   getVar(name).unshift(value)
 }
 // Normal functions
 function assert(condition=true, callback=()=>{println("You forgot")}, fallback=()=>{}) {
   if (condition) {
     callback()
   } else if (fallback) {
     fallback()
   }
 }
 function input(name="x") {
   return new Promise((resolve) => {
     rl.question(`?> `, (input) => {
       setVar(name, input)
       resolve()
     })
   })
 }
 function exit(code=0) {
   process.exit(code)
 }
 function tryCatch(tryBlock=()=>{println("You forgot")}, catchBlock=e=>{console.error("You forgot\n"+e)}) {
   try {
     tryBlock()
   } catch (e) {
     catchBlock(e)
   }
 }
 // File functions
 function readFile(filename="youForgot.txt", name="x") {
   setVar(name, fs.readFileSync(filename,
     { encoding: 'utf8', flag: 'r' }))
 }
 function writeFile(filename="youForgot.txt", data="You forgot to give some data") {
   fs.writeFileSync(filename, data)
 }
 // Random functions
 function randomInt(min=0, max=10) {
   return Math.floor(Math.random() * (max - min + 1)) + min
 }
 function randomFloat(min=0, max=1) {
   return Math.random() * (max - min) + min
 }
 function randomString(len=15) {
   const charList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789~`!@#$%^&*()-_+={[}]|\\:;\"'<,>.?/"
   let result = 
   for (let i = 0; i < len; i++) {
     result += charList[randomInt(0, charList.split("").length)]
   }
   return result
 }
 function randomItemOfArray(array=["You", "forgot", "to", "give", "an", "argument"]) {
   return array[Math.floor(Math.random() * array.length)]
 }
 // Date and time function
 function getCurrentTime() {
   const currentDate = new Date()
   const year = currentDate.getFullYear()
   const month = currentDate.getMonth() + 1
   const day = currentDate.getDate()
   const hours = currentDate.getHours()
   const minutes = currentDate.getMinutes()
   const seconds = currentDate.getSeconds()
   const formattedDate = `${day}.${month}.${year} ${seconds}:${minutes}:${hours}`
   return formattedDate
 }
 // Encryption functions
 function threeLettersBack(text="You forgot") {
   let result = 
   for (let i = 0; i < text.length; i++) {
     let char = text[i]
     if (char.match(/[a-z]/i)) {
       const code = text.charCodeAt(i)
       let shiftAmount = 3 % 26
       let shiftedCode = code
       if (code >= 65 && code <= 90) {
         shiftedCode = ((code - 65 + shiftAmount) % 26) + 65
       } else if (code >= 97 && code <= 122) {
         shiftedCode = ((code - 97 + shiftAmount) % 26) + 97
       }
       result += String.fromCharCode(shiftedCode)
     } else {
       result += char
     }
   }
   return result
 }
 function threeLettersForward(text="You forgot") {
   let result = 
   for (let i = 0; i < text.length; i++) {
     let char = text[i]
     if (char.match(/[a-z]/i)) {
       const code = text.charCodeAt(i)
       let shiftAmount = -3 % 26
       let shiftedCode = code
       if (code >= 65 && code <= 90) {
         shiftedCode = ((code - 65 + shiftAmount) % 26) + 65
       } else if (code >= 97 && code <= 122) {
         shiftedCode = ((code - 97 + shiftAmount) % 26) + 97
       }
       result += String.fromCharCode(shiftedCode)
     } else {
       result += char
     }
   }
   return result
 }

Execution

So, you have everything set up and you want to run it, but how? Well, first you have to get to the directory where the index.js and defenitions.js is located and then run this command:

 node . path/to/your/program.funky

Note: change "path/to/your/program.funky" to where your funky program is located.
And your program should successfully work!