Author Topic: Vala  (Read 7553 times)

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Vala
« on: April 16, 2011, 05:23:08 PM »
Armando posted some examples of using the Vala/Genie to C translator if your interested in this language environment.

Quote from: AIR
Has anyone looked into the Vala language?  It seems pretty cool.

I converted the Tiny Times example I did using Glade as a test:

Code: [Select]
using Gtk;

Window window;
TextView textview;

public void button_clicked (Button source) {
  var buf="";
  var A = source.label;
  
  for (int i = 1; i <= 15; i++) {
    var res = i*A.to_int();
    buf += "  " + A + " x " + i.to_string() + " = " + res.to_string() + "\n";
  }

  textview.buffer.text = buf;
}

int main (string[] args) {    
    Gtk.init (ref args);

    try {
        var builder = new Builder ();
        builder.add_from_file ("tt.ui");
        builder.connect_signals (null);
        window = builder.get_object ("window1") as Window;
        textview = builder.get_object ("textview1") as TextView;
        window.show_all ();
        Gtk.main ();
    } catch (Error e) {
        stderr.printf ("Could not load UI: %s\n", e.message);
        return 1;
    }

    return 0;
}

What's really nice about it is that you can code in an OO way (which my example is NOT) with all of it's benefits, but it comes out as "C", not "C++" and no extra "bloat".

It's modelled somewhat after C#, but no runtime.  It uses GLib/GTK.

A.



Quote from: AIR
Vala supports two syntax modes: "Vala" mode, which is like C#, and "Genie" mode which is like Python.

Here is the same example coded using Genie syntax:

Code: [Select]
[indent=2]
uses
  Gtk

window:Window
textview:TextView
  
init
  Gtk.init (ref args)

  try
    var builder = new Builder ()
    builder.add_from_file ("tt.ui")
    builder.connect_signals (null)
    window = builder.get_object ("window1") as Window
    textview = builder.get_object ("textview1") as TextView
    window.show_all ()
    Gtk.main ()
  except e : Error
    print "%s", e.message
  
def button_clicked(source:Button)
  var buf=""
  var A=source.label
  
  for var i = 1 to 15
    var res = i*A.to_int()
    buf += "  " + A + " x " + i.to_string() + " = " + res.to_string() + "\n"
    textview.buffer.text = buf

Quote from: AIR
How is string support with Vala? One of the major reasons I use ScriptBasic is I have virtually unlimited strings and I don't have to do a thing to declare or release them.

Using Project Gutenberg's "War and Peace", which weighs in at 3.1Megs:

Code: [Select]
[indent=2]
init
  book:string = "Hello"

  print("Initial String Variable Size: %d bytes",book.length)

  try
    FileUtils.get_contents("2600.txt", out book)
  except e : Error
    print("%s", e.message)

  print("String Variable Size after loading \"War and Peace\" from file: %d bytes", book.length)

  var x = book.split("\n")

  print("Number of lines in \"War and Peace\": %d",x.length)

Quote from: Output
Initial String Variable Size: 5 bytes
String Variable Size after loading "War and Peace" from file: 3288739 bytes
Number of lines in "War and Peace": 65337


Hope that answers your question!

A.

Quote from: AIR
Quote
They support MySql, LibXml2, SQlite, WebKit, and far more.....

I was surprised to see that cURL (libcurl) wasn't in the package list. I count on that library a lot.

That list only contains the "official" packages.  libsoup is generally considered as the replacement, although it's not a simple "drop-in" replacement.

Anyway, the Maemo project (which Vala supports) has something in their scm for curl, which I've attached.

Unpack it, and copy the two files into your vapi folder (if you built 0.12.0 from source using the defaults, it should be located at /usr/local/share/vala-0.12/vapi/)

curl.gs
Code: [Select]
/*
  compile with: valac --pkg curl curl.gs -X -lcurl
*/

[indent=2]
uses
  Curl
  
init
  var fp1 = FileStream.open("general.html","w")
  var handle = new EasyHandle()
  handle.setopt(Option.URL, "http://scriptbasic.com/html/general.html")
  handle.setopt(Option.FILE, fp1)
  handle.perform()

Note that because of the way Vala/Genie works, you don't need to close the file handle or the curl handle because they are automatically closed when they go out of scope.  So if you were to place either in a sub/function, when that sub/function was exited the handles would be closed.

In this case, they are closed as the program exits.

Note also that by using "var" above, I don't have to "pre-declare" the variables.  valac infers the type based on what comes after the "=" sign, and sets the type accordingly.

A.
cURL Vala Attachment

Quote from: AIR
Here's an idea for MySQL.  Not tested because I don't have it running:

Code: [Select]
/*
  compile with: valac --pkg mysql mysql.gs -X -lmysqlclient
*/

[indent=2]
uses
  Mysql

init
  MysqlHost: string = ""
  UserName: string = ""
  Password: string = ""
  DatabaseName: string = ""
  
  var MysqlDB = new Mysql.Database()
  MysqlDB.real_connect(MysqlHost, UserName, Password, DatabaseName,  0,"/tmp/mysql.sock")
  
  var ReturnValue = MysqlDB.query("SELECT ")
  var ResultSet = MysqlDB.use_result()
  
  while !ResultSet.eof()
    var MyRow = ResultSet.fetch_row()
    if MyRow is not null
      print " %s |  %s", MyRow[0], MyRow[1]

A.

Quote from: AIR
xmltest.vala
Code: [Select]
/*
  Compile with: valac --pkg libxml-2.0 xmltest.vala -X -lxml2
*/

using Xml;

class XmlParser {

    public void parse_file (string path) {
        Xml.Doc* doc = Parser.parse_file (path);
        if (doc == null) {
            printerr("File %s not found or permissions missing\n", path);
            return;
        }

        Xml.Node* root = doc->get_root_element ();
        if (root == null) {
            delete doc;
            printerr("The xml file '%s' is empty\n", path);
            return;
        }

        parse_node(root);
        delete doc;
    }

    private void parse_node (Xml.Node* node) {

        for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {
            if (iter->type != ElementType.ELEMENT_NODE) {
                continue;
            }

            string node_name = iter->name;
            string node_content = iter->get_content();
            if (node_content.index_of("  ")==-1)
              print("%s=%s\n",node_name,node_content);

            parse_node(iter);
        }
    }
}

int main (string[] args) {

    if (args.length < 2) {
        stderr.printf ("Argument required!\n");
        return 1;
    }

    Parser.init();

    var sample = new XmlParser();
    sample.parse_file (args[1]);

    Parser.cleanup();

    return 0;
}

Quote from: AIR
Here's the same thing in GENIE:

xmltest.gs
Code: [Select]
/*
  Compile with: valac --pkg libxml-2.0 xmltest.gs -X -lxml2
*/

[indent=2]

uses
  Xml
  
class XmlParser

  def parse_file (path: string )
    doc: Xml.Doc*
    root: Xml.Node*

    doc = Parser.parse_file (path)
    if doc is null
      printerr ("File %s not found or permissions missing\n", path)
      return

    root = doc->get_root_element()
    if root is null
      delete doc
      printerr ("The xml file '%s' is empty\n", path)
      return

    parse_node (root)
    
    delete doc
    
    
  def private parse_node (node: Xml.Node*)  
    
    iter: Xml.Node* = node->children
    
    while (iter != null)
      if (iter->type != ElementType.ELEMENT_NODE)
        iter = iter->next
        continue

      var node_name = iter->name
      var node_content = iter->get_content()
      if (node_content.index_of("  ")==-1)
        print("%s=%s",node_name,node_content)

      parse_node(iter)
      iter = iter->next


init

  if (args.length < 2)
    printerr("Argument required!\n")
    return
  Parser.init ()
    
  var sample = new XmlParser()

  sample.parse_file (args[1])

  Parser.cleanup ()
  

Quote from: AIR
Code: [Select]
uses
  Curl
  Xml
  Mysql

OR

Code: [Select]
uses Curl, Xml, Mysql
You would most likely want to place each code block in a class so you could reuse it, but it's not neccessary.

If you put all of the code in a single file:
Code: [Select]
valac <file> --pkg curl --pkg libxml-2.0 --pkg mysql  -X -lcurl -X -lxml2 -X -lmysqlclient
if you put them in separate files:
Code: [Select]
valac <file> <file> <file> --pkg curl --pkg libxml-2.0 --pkg mysql  -X -lcurl -X -lxml2 -X -lmysqlclient
You could create a makefile or bash script to simplify things...

For readability, you can also group the related --pkg and -X and separate by spaces:

Code: [Select]
valac <file> --pkg curl -X -lcurl      --pkg libxml-2.0 -X -lxml2      --pkg mysql  -X -lmysqlclient
A.

Quote from: AIR

curl.gs
Code: [Select]
/*
  compile with: valac --pkg curl curl.gs -X -lcurl
*/

[indent=2]
uses
  Curl
  
init
  var fp1 = FileStream.open("general.html","w")
  var handle = new EasyHandle()
  handle.setopt(Option.URL, "http://scriptbasic.com/html/general.html")
  handle.setopt(Option.FILE, fp1)
  handle.perform()

Quote from: AIR
Here's the same thing using libsoup:
Code: [Select]
[indent=2]
/* Build with valac --thread --pkg libsoup-2.4 yourfile.gs */
uses
  Soup
 
init
  var session = new Soup.SessionAsync ()
  var message = new Soup.Message ("GET", "http://scriptbasic.com/html/general.html")
  session.send_message (message)
  try
    FileUtils.set_contents("general.html", (string)message.response_body.data)
  except e: Error
    print("%s",e.message)

A.

« Last Edit: April 21, 2011, 04:58:02 PM by ABB »

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: Vala
« Reply #1 on: April 25, 2011, 01:16:57 PM »
I was able to get Vala compiled from source on Ubuntu 10-10 64 bit. I had to install flex & bison and do a ldconfig after the install but all went well. I continue to follow along with Armando's adventures with Vala/Genie as his comfort level increases with his new environment.