Skip to content

Commit

Permalink
WOOOOOOOOOOOOOO 100TH COMMIT!
Browse files Browse the repository at this point in the history
Tried a new approach to the documentation system. Worked out pretty well;
extremely easy to document commands (automates the boring work; each
library has only one file)
  • Loading branch information
bluebear94 committed Feb 9, 2014
1 parent 1e3cc7c commit 0f181d0
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 3 deletions.
123 changes: 123 additions & 0 deletions docs/std.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#add
desc "Adds zero or more values. Will return a value with the most generalized type. If all arguments are strings, then concatenates them."
vector
throws 1
#subt
desc "Subtracts zero or more values from the first argument. Will return a value with the most generalized type."
vector
throws 1
#mult
desc "Multiplies zero or more values. Will return a value with the most generalized type."
vector
throws 1
#div
desc "Divides zero or more values from the first argument. Will always return a floating-point value."
vector
throws 1
#idiv
desc "Integer divides zero or more values from the first argument. Note that this does not accept floating-point values."
vector
throws 1
#mod
desc "Finds the remainder of two integers. If more than two arguments are present, folds the operation from left to right."
vector
throws 1
#hluna
desc "Displays the argument to the homescreen in the GUI. It might also be useful to note that the value is also shown in the terminal with the prefix `[hluna]'."
#negate
desc "Returns the additive inverse of an argument."
vector
throws 1
#avg
desc "Takes the average of two numbers."
vector
throws 1
#eq
desc "Returns true if two values are equal; false otherwise."
vector
#neq
desc "Returns true if two values are unequal; false otherwise."
vector
#gt
desc "Returns true if the first value is greater than the second; false otherwise."
vector
#lt
desc "Returns true if the first value is less than the second; false otherwise."
vector
#ge
desc "Returns true if the first value is greater than or equal to the second; false otherwise."
vector
#le
desc "Returns true if the first value is less than or equal to the second; false otherwise."
vector
#abs
desc "Returns the absolute value of a number."
vector
throws 1
#cons
desc "Returns an element prepended to a list or string."
throws 1
#car
desc "Returns the first element of a list or string."
throws 1
#cdr
desc "Returns a list containing all but the first element of a list or string."
throws 1
#econs
desc "Returns an element appended to a list or string."
throws 1
#ecar
desc "Returns the last element of a list or string."
throws 1
#ecdr
desc "Returns a list containing all but the last element of a list or string."
throws 1
#expr
desc "Evaluates the amethyst expression passed as an argument."
#len
desc "Returns the length of a list, string, or number."
throws 1
#now
desc "Returns the current time in milliseconds after Jan. 1, 1970."
#sub
desc "Returns the subcollection of the collection #1 from index #2 to #3 (or the end if #3 is undefined)."
throws 1
#str
desc "Returns the string representation for any value. Useful for concatenating to strings."
#rrbzo
desc "Returns a random real between zero and one. Might return 0, but never returns 1."
#floor
desc "Returns the floor of the number."
throws 1
#fpart
desc "Returns the fractional part of the number."
throws 1
#map
desc "Maps one or more lists to a function (the last argument). All lists must have the same length."
throws 1
#foldl
desc "Given a list (#1), a base value (#2), and a function (#3), applies #3 over #2 and each element of #1 (starting from the first)."
throws 1
#foldr
desc "Given a list (#1), a base value (#2), and a function (#3), applies #3 over #2 and each element of #1 (starting from the last)."
throws 1
#filter
desc "Returns a list with all of the elements of #1 which, when passed to #2, return true values."
throws 1
#dsa
desc "Returns a disassembly of a function. Useful in debugging the compiler."
throws 1
#hsort
desc "Returns a sorted array. This function also needs a comparison function. Heapsort, which always has an O(n log n) time complexity and an O(1) space complexity but is not stable and is generally slower than quicksort, is used for this function."
throws 1
#qsort
desc "Returns a sorted array. This function also needs a comparison function. Quicksort, which may occasionally have an O(n^2) time complexity (although use of randomization guarantees O(n log n) complexity in virtually all cases) but is stable unlike heapsort, is used for this function."
throws 1
#msort
desc "Returns a sorted linked list. This function also needs a comparison function. An implementation of mergesort for linked lists, which has an O(n log n) time complexity and O(1) space complexity, is used."
throws 1
#help
desc "Help function."
#ribzpt
desc "Returns a random integer between a zero and a power of 2 (2^#1)."
throws 1
2 changes: 1 addition & 1 deletion src/main/scala/cmdreader/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object Global {
val TWO = new BigInteger("2")
val vM = 0
val vm = 5
val vr = 18
val vr = 19
val vrr = "-alpha"
val version = "v" + vM + "." + vm + "." + vr + vrr
val r: Random = new Random
Expand Down
43 changes: 43 additions & 0 deletions src/main/scala/cmdreader/std/Help.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cmdreader.std

import cmdreader._
import types._
import gui._
import eloro._
import scala.math.BigInt

class Help extends Command {
override def getName(): String = "help"
override def isValidArg0(n: Int): Boolean = n <= 1
override def apply(args: Array[Type]): Type = {
val ZERO = TMountain(0)
val ONE = TMountain(1)
if (args.length != 0) {
args(0) match {
case TString(s) => Main.println(DocGen.getHelp(s))
case ZERO => {
Main.println("Available commands:")
for (l <- Global.liblist) {
Main.println(" In library " + l._1 + ":")
var s = " "
for (c <- l._2.commandList) {
s += c._1 + " "
}
Main.println(s)
}
}
case ONE => {
Main.println("About Amethyst\n\nWritten by bluebear94 in Scala\nWith help from [name withheld]")
}
case _ => Main.println("Unrecognized value")
}
}
else {
Main.println("""To search for a specific built-in command, pass the complete command name
|(if the library name is std, then it may be omitted) as an argument.
|Pass 0 as an argument to list all available commands.
|Pass 1 as an argument to see info about this program.""".stripMargin)
}
new TVoid
}
}
1 change: 1 addition & 0 deletions src/main/scala/cmdreader/std/Loader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@ class Loader {
Global.liblist("std").loadCmd("MSort")
Global.liblist("std").loadCmd("Ribzpt")
Global.liblist("std").loadCmd("OAug")
Global.liblist("std").loadCmd("Help")
}
}
2 changes: 1 addition & 1 deletion src/main/scala/cmdreader/std/OAdd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ class OAdd extends CommandOperator {
def getPrecedence() = PStandard.ADD_SUBT
def isReversed() = false
def hasAssignmentEquiv() = true
def getDoubleBase() = Some(new TMountain(BigInteger.ONE))
def getDoubleBase() = Some(new TMountain(1))
}
2 changes: 1 addition & 1 deletion src/main/scala/cmdreader/std/OSubt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ class OSubt extends CommandOperator {
def getPrecedence() = PStandard.ADD_SUBT
def isReversed() = false
def hasAssignmentEquiv() = true
def getDoubleBase() = Some(new TMountain(BigInteger.ONE))
def getDoubleBase() = Some(new TMountain(1))
}
99 changes: 99 additions & 0 deletions src/main/scala/eloro/DocGen.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package eloro

import types._
import cmdreader._
import scala.util.parsing.combinator._
import scala.collection.immutable.HashMap
import scala.util.parsing.input._
import java.io._
import java.util.Scanner
/**
* Documentation generator. Called through the $:help command.
* @author bluebear94
*/
object DocGen {
def getProperties(cmd: Command): String = {
val arglist = List.range(0, 20).filter(cmd.isValidArg0(_))
val argstr = "\nValid argcounts: " + arglist.mkString(", ") + (if (arglist.filter(_ > 10).isEmpty) "" else ", ...")
val opProperties = cmd match {
case op: CommandOperator => {
val alias = op.getOpAlias
val hasae = op.hasAssignmentEquiv
val db = op.getDoubleBase
val prec = op.getPrecedence
val un = op.isUnary
val isrtl = op.isReversed
val dm = db match {
case Some(t) => {
"\n" + alias + alias + "a is equivalent to a " + alias + "= " + t
}
case None => ""
}
"\nOperator equivalent: " + alias + "\nPrecedence: " + prec + "\nUnary: " + (if (un) "Yes" else "No") + "\n" +
(if (isrtl) "Right-to-left" else "Left-to-right") + (if (hasae) "\nAssignment Equiv.: " + alias + "=") + dm
}
case _ => ""
}
cmd.getName + argstr + opProperties
}
val cmdl: HashMap[String, (List[String]) => String] = HashMap(
("desc", _.head),
("vector", _ => "If applied to one or more lists, this function will apply element-by-element."),
("throws", (a: List[String]) => "Throws: " + a.mkString(", ")))
def out(c: String, a: List[String]) = {
if (cmdl.isDefinedAt(c)) cmdl(c)(a)
else throw new NoSuchDocCommandException("Command not found: " + c)
}
def parseCmd(ln: String) = {
val p = new EP
import p._
val pp = phrase(line)
val ret = pp(new CharSequenceReader(ln))
ret match {
case Success(res, t) => out(res._1, res._2)
case NoSuccess(msg, t) => {
println(ret)
throw new RuntimeException("Could not parse: " + msg + " in line: " + ln)
}
}
}
def getHelp(name: String) = {
if (name.charAt(0) != '$' || name.indexOf(":") == -1) "Invalid command name"
else {
val bp = getProperties(Global.getCmdno(name.substring(1)))
val l = name.substring(1, name.indexOf(":"))
val n = name.substring(name.indexOf(":") + 1)
val lib = if (l == "") "std" else l
val s = new Scanner(new File("docs/" + lib + ".txt"))
var txt = ""
while (txt != ("#" + n) && s.hasNextLine) {
txt = s.nextLine
}
var details = ""
def readAndAppend = {
txt = s.nextLine
if (!txt.startsWith("#")) details += "\n" + parseCmd(txt)
}
if (s.hasNextLine) readAndAppend
while (!txt.startsWith("#") && s.hasNextLine) {
readAndAppend
}
bp + details
}
}
}
class NoSuchDocCommandException(msg: String) extends RuntimeException
/**
* Parser class for doc commands.
*/
class EP extends RegexParsers with PackratParsers {
override def skipWhitespace = false
lazy val quoted: PackratParser[String] = "\"" ~> "[^\"]*".r <~ "\""
lazy val unquoted: PackratParser[String] = regex("[^\"\\s]*".r)
lazy val args: PackratParser[List[String]] = repsep(quoted | unquoted, " ")
lazy val lineA: PackratParser[(String, List[String])] = unquoted ~ " " ~ args ^^ {
case uq ~ _ ~ a => (uq, a)
}
lazy val lineB: PackratParser[(String, List[String])] = unquoted ^^ {s: String => (s, Nil)}
lazy val line = lineA | lineB
}

0 comments on commit 0f181d0

Please sign in to comment.