SourceForge.net Logo
P Y N T
v0.1.0

Pynt is a scripting langauge designed to simplify running builds. It is similar in purpose to Ant (and the first version was similar in feel to Python, hence the name). You can download it here.

The main benefits of Pynt over Ant are:
The Pynt language will most likely change drastically before the 1.0.0 release. Any feedback is appreciated.

Sample:

Below is a pynt script that compiles pynt and runs its tests:


import files j2sdk antlr junit

method Package(name, depends=[], jars=[])
    return this
end

# Define the dependencies between the packages

ast = Package("ast")
antlr = Package("antlr", [ast], ["lib\antlr-2.7.2-lib.jar"])
types = Package("types", [ast])
engine = Package("engine", [ast, types])
all = Package("junit", [ast, antlr, types, engine], ["lib\jdom-b8-lib.jar", "lib\xercesImpl.jar", "lib\jdom-b8-lib.jar", "lib\junit-3.8.1-lib.jar", "lib\xom-1.0d16-lib.jar", "lib\antlr-2.7.2-lib.jar"])

target Generate
    print "Generating..."
    return Antlr(
        grammar = "../antlr/pynt.g",
        output = "temp/src/org/pynt/antlr"
    )
end

target Compile<package>
    build Generate

    classpath = package.jars
    for depend in package.depends
        result = build Compile<depend>
        classpath += [result.output]
    end
    print "Compiling " + package.name + "..."
    filter = "org/pynt/" + package.name + "/*.java"
    Copy(Scan("src", filter), "temp\" + package.name)
    files = Scan("temp/" + package.name, filter) + Scan("temp/src", filter)
    return Javac(source="1.4", targ="1.4", output="temp\" + package.name, files=files, classpath=package.jars)
end

target Test
    result = build Compile<all>
    print result.classpath + [result.output]
    JUnit (suite = "org.pynt.junit.AllTests", classpath = result.classpath + [result.output])
end

Intalling And Running Pynt:

To install Pynt, just unzip the downloaded file. You can then run it from the command line like this:

java -jar <install dir>/pynt.jar

This will run Pynt in "interactive mode", meaning you can enter commands at the prompt and Pynt will execute them immediately. For example:

pynt> print "Hello World"
Hello World

You can also have Pynt execute the contents of a file. For example, if we put our "print" statement in a file called "helloworld.pynt", we could run it like this:

java -jar <install dir>/pynt.jar helloworld.pynt

To execute some Pynt code directly from the command line, you can use the "-c" option (you'll need to escape any special characters within the quotes):

java -jar <install dir>/pynt.jar -c "print \"Hello World\""

Constants and Variables:

You can define a variable in Pynt by assigning a value to a name:

pynt> msg = "Hello World"
pynt> print msg
Hello World

Variables cannot be defined more than once:

pynt> msg = "Foo"
pynt> msg = "Bar"
Variable "msg" already exists

If you want the ability to modify the value after it's been defined, you'll need to use the "set" keyword to override the defintion:

pynt> msg = "Foo"
pynt> set msg = "Bar"
pynt> print msg

Hello World

Numbers:

You can create a java.math.BigDecimal object using a series of digits.

pynt> print 100
100

Strings:

You can create a java.lang.String object by placing text between double qutoes. Within the string, curly brackets can be used to reference other variables:

pynt> module = "framework"
pynt> print "Compiling {module}"
Compiling framework

Files:

Under construction

FileSets:

Under construction

Sets:

You can use curtly brackets to create a set:

myjars = { "foo.jar", "bar.jar"  }


Lists:

You can use squate brackets to create a list:

myjars = [ "foo.jar", "bar.jar"  ]


Java Objects:

Normal Java objects can be loaded and instantiated in Pynt. The class needs to be loaded first, then you can create an instance of the class using the "new" method:

pynt> load java.util.Date
pynt> print Date.new()
Mon Apr 21 13:36:27 GMT 2003

Methods can be invoked the way you'd expect:

pynt> load java.util.Date
pynt> load java.text.DateFormat
pynt> print DateFormat.getDateInstance().format(Date.new())
Apr 30, 2003


All classes (including those in java.lang) must be explicitly imported before use. Unlike Java, you cannot use fully qualified names.

The "from" statement can be used to load classes from jars and directories that aren't part of the system classpath (classes that you've just compiled, for example). The "from" statement creates a new classloader, and all "import" statements within the "from" block will use that classloader. For example:

pynt> import com.acme.tools.MyTool from "mytool.jar"
pynt> MyTool.new().run()

Pynt Objects:

You cannot define classes in Pynt. However, you can use the "this" keyword to return an object representing the current stack frame. For example:

method Person(name)
    return this
end

pynt> person = Person("
Horatio McAllister")
pynt> print person.name

Horatio McAllister

This can be particular handy when chaining together commands, where the output of each command is the input to the next command. For example, assuming our Javac and Jar functions end with a "return this", we can use the output of the Javac as an input to the Jar:

javac = Javac(output="build", ...)
jar = Jar(input=javac.output, ...)

Methods:

You can defined methods on Pynt objects by using the "method" keyword.

method PrintTwice(name)
    print name
    print name
end

PrintTwice("Hello World")
Hello World
Hello World

Targets and Builds:

Targets are similar to methods. However, they cannot be invoked directly. What looks like an invocation actually creates a reference to the target with the specified arguments. These references must be passed into a "build" statement to run the targets:

target Compile<dir>
    print "Compiling " + dir
    ...
end
build Compile<"src">

The brackets on a target with no arguments are optional (unlike the parens on a method, which are madatory):

target Compile
    print "Compiling"
    ....
end
build comple
   
Targets can also build other targets. This is basically how you represent dependencies between targets:

target Compile
    ...
end

target Test
    build Compile
    ...
end
      
The key difference between methods and targets is that within a build (the first call to a "build" statement starts a build, and the build ends when it returns), a target will never be invoked more than once with the same parameters. For example:


target Compile<module>
    print module
end

target All
    build compile<"foo">
    build compile<"bar">
    build compile<"foo">
end

pynt> build All
foo
bar

Note that the "compile" target only gets built once with the "foo" argument, even though it's called twice from the "all" target.

Projects:

Pynt code can be spread across multiple files, and each file is called a "project". You can reference other projects by using the "load" command. For example, let's say we had a file called "printer.pynt":

method PrintTwice(name)
    print name
    print name
end

We can reference the method in this file as follows:

pynt> import printer
pynt> PrintTwice("Hello World")

Hello World
Hello World 

This works for methods, targets, constants, and variables. You can
basically  think of the load statement as creating a reference to the other project's "root" object. Pynt will only load each project once, so if multiple projects import a common project, they will all get references to the same root object.

By default Pynt looks for project files in the current directory and in the directory where Pynt is installed. This can be overridden by using the "-p" command line option however.