#!/usr/bin/env nit # Microbenchmak generation for multiple language # Just a quick an dirty Nit script file :) # This benchmark focuses on effects of the hierarchy dept # on the typetest performances # class Root # class Klass[E] super Root # class C1...CX super Root # Klass[CX] isa Klass[C1] class Klass var id: Int var supers = new Array[Klass] var all_supers = new HashSet[Klass] redef fun to_s do return "C{id}" end end class Generator var classes = new Array[Klass] var dept = 5 var loops = 50000 var middle = 0 var dry = false var check = false fun genhier do var s: nullable Klass = null for d in [1..dept] do var c = new Klass(d) classes.add(c) c.all_supers.add(c) if s != null then c.supers.add(s) c.all_supers.add_all(s.all_supers) end s = c end middle = (dept + 1) / 2 end var file: nullable OFStream = null fun write(str: String) do file.write(str) file.write("\n") end fun writenit(dir: String, name: String) do dir = "{dir}/nit" dir.mkdir file = new OFStream.open("{dir}/{name}.nit") write "class Root\n\tfun id: Int do return 0\nend" for c in classes do write "class {c}[E]" if c.supers.is_empty then write "\tsuper Root" else for s in c.supers do write "\tsuper {s}[E]" end write "\tredef fun id do return {c.id}" write "end" end write "fun test(a,b: Root, loops, start: Int)" write "do" write "var x = start" write "var i = 0" write "while i < loops do" write "\tvar j = 0" write "\twhile j < loops do" var test if dry then test = "" else test = "a isa {classes[middle]}[Root] and " write "\t\tif {test}x >= 0 then" if check then write "\t\tx += 1" write "\telse" write "\t\t\tx -= 1" write "\t\t\ta = b" write "\t\tend" write "\t\tj += 1" write "\tend" write "\ti += 1" write "end" write "print x" write "end" write "var a:{classes.first}[Root] = new {classes.last}[Root]" write "var b:{classes.first}[Root] = new {classes.first}[Root]" for c in classes do write "\t\t\tif a.id > 0 then a = new {c}[Root]" end write "test(b, b, 10, -100)" write "test(a, a, {loops}, 0)" file.close end fun writejava(dir: String, name: String, interfaces: Bool) do dir = "{dir}/java" dir.mkdir file = new OFStream.open("{dir}/{name}.java") var cl = "" if interfaces then cl = "X" write "class {name} \{" if interfaces then write "static interface Root\n\t\{ int id(); \}" else write "static class Root\n\t\{ int id() \{ return 0;\} \}" end for c in classes do if interfaces then write "static interface {c} " else write "static class {c} " end if c.supers.is_empty then write "\textends Root" else for s in [c.supers.first] do write "\textends {s}" end if interfaces then write "\{\}" write "static class X{c} implements {c}" end write "\{" write "\tpublic int id() \{ return {c.id}; \}" write "\}" end write "static public void main(String args[]) \{" if interfaces then write "\t{classes.first} a = new X{classes.last}();" write "\t{classes.first} b = new X{classes.first}();" for c in classes do write "\t\t\tif (a.id() > 0) a = new X{c}();" end else write "\t{classes.first} a = new {classes.last}();" write "\t{classes.first} b = new {classes.first}();" for c in classes do write "\t\t\tif (a.id() > 0) a = new {c}();" end end write "\ttest(b, b, 10, -100);" write "\ttest(a, a, {loops}, 0);" write "\}" write "static public void test({classes.first} a, {classes.first} b, int loops, int start) \{" write "\tint x = start;" write "\tfor(int i = 0; i < loops; i++) \{" write "\t\tfor(int j = 0; j < loops; j++) \{" var test if dry then test = "" else test = "a instanceof {classes[middle]} && " write "\t\t\tif({test}x>=0) \{" if check then write "\t\t\t\tx += 1" write "\t\t\t\} else \{ x--; a = b;\}" write "\t\t}" write "\t\}" write "\tSystem.out.println(x);" write "\}" write "\}" file.close end fun writecsharp(dir: String, name: String, interfaces: Bool) do dir = "{dir}/cs" dir.mkdir file = new OFStream.open("{dir}/{name}.cs") var cl = "" if interfaces then cl = "X" write "class {name} \{" if interfaces then write "interface Root\n\t\{ int Id(); \}" else write "class Root\n\t\{ public int Id() \{ return 0;\} \}" end for c in classes do if interfaces then write "interface {c} " else write "class {c} " end if c.supers.is_empty then write "\t: Root" else for s in [c.supers.first] do write "\t: {s}" end if interfaces then write "\{\}" write "class X{c} : {c}" end write "\{" write "\tpublic int Id() \{ return {c.id}; \}" write "\}" end write "static void Main(string[] args) \{" if interfaces then write "\t{classes.first} a = new X{classes.last}();" write "\t{classes.first} b = new X{classes.first}();" for c in classes do write "\t\t\tif (a.Id() > 0) a = new X{c}();" end else write "\t{classes.first} a = new {classes.last}();" write "\t{classes.first} b = new {classes.first}();" for c in classes do write "\t\t\tif (a.Id() > 0) a = new {c}();" end end write "\tTest(b, b, 10, -100);" write "\tTest(a, a, {loops}, 0);" write "\}" write "static void Test({classes.first} a, {classes.first} b, int loops, int start) \{" write "\tint x = start;" write "\tfor(int i = 0; i < loops; i++) \{" write "\t\tfor(int j = 0; j < loops; j++) \{" var test if dry then test = "" else test = "a is {classes[middle]} && " write "\t\t\tif({test}x>=0) \{" if check then write "\t\t\t\tx++;" write "\} else \{ x--; a = b; \};" write "\t\t}" write "\t\}" write "\tSystem.Console.WriteLine(x);" write "\}" write "\}" file.close end fun writescala(dir: String, name: String, interfaces: Bool) do dir = "{dir}/scala" dir.mkdir file = new OFStream.open("{dir}/{name}.scala") var cl = "" write "object {name} \{" write "class Root\n\t\{ def id: Int = 0 \}" for c in classes do if interfaces then write "trait {c}[E] " else write "class {c}[E] " end if c.supers.is_empty then write "\textends Root" else for s in [c.supers.first] do write "\textends {s}[E]" end if interfaces then write "\{\}" write "class X{c}[E] extends {c}[E]" end write "\{" write "\toverride def id: Int = {c.id}" write "\}" end write "def main(args: Array[String]) = \{" if interfaces then write "\tvar a:{classes.first}[Root] = new X{classes.last}[Root]()" write "\tvar b:{classes.first}[Root] = new X{classes.first}[Root]()" for c in classes do write "\t\t\tif (a.id > 0) a = new X{c}[Root]();" end else write "\tvar a:{classes.first}[Root] = new {classes.last}[Root]()" write "\tvar b:{classes.first}[Root] = new {classes.first}[Root]()" for c in classes do write "\t\t\tif (a.id > 0) a = new {c}[Root]();" end end write "\ttest(b, b, 10, -100)" write "\ttest(a, a, {loops}, 0)" write "\}" write "def test(aa:{classes.first}[Root], b:{classes.first}[Root], l: Int, start: Int) = \{" write "\tvar a = aa" write "\tvar x = start" write "\tvar loops = l" write "\tvar i = 0" write "\twhile (i < loops) \{" write "\t\tvar j = 0" write "\t\twhile (j < loops) \{" var test if dry then test = "" else test = "a.isInstanceOf[{classes[middle]}[Root]] && " write "\t\tif ({test}x>=0) \{" if check then write "\t\t\tx += 1" write "\} else \{ x = x - 1; a = b; \}" write "\t\tj += 1" write "\t\t\}" write "\ti += 1" write "\t\}" write "\t\t\tprintln(x)" write "\}" write "\}" file.close end fun writecpp(dir: String, name: String) do dir = "{dir}/cpp" dir.mkdir file = new OFStream.open("{dir}/{name}.cpp") write "#include " write "#include " write "class Root\n\t\{ public: virtual int id() \{ return 0;\} \};" for c in classes do write "template" write "class {c} " if c.supers.is_empty then write "\t: public virtual Root" else for s in [c.supers.first] do write "\t: public virtual {s}" end write "\{" write "\tpublic: virtual int id() \{ return {c.id}; \}" write "\};" end write "void test({classes.first}* a, {classes.first}* b, int loops, int start) \{" write "\tint x = start;" write "\tfor(int i = 0; i < loops; i++) \{" write "\t\tfor(int j = 0; j < loops; j++) \{" var test if dry then test = "" else write "\t\t\t{classes[middle]}* to = dynamic_cast<{classes[middle]}*>(a);" test = "to != 0 &&" end write "\t\tif({test}x>=0) \{" if check then write "\t\t\tx += 1" write "\} else \{ x--; a = b;\}" write "\t\t}" write "\t\}" write "\tstd::cout << x << std::endl;" write "\}" write "int main(int argc, char **argv) \{" write "\t{classes.first}* a = new {classes.last}();" write "\t{classes.first}* b = new {classes.first}();" for c in classes do write "\t\t\tif (a->id() > 0) a = new {c}();" end write "\ttest(b, b, 10, -100);" write "\ttest(a, a, {loops}, 0);" write "\}" file.close end fun writee(dir: String, name: String, se: Bool) do if se then dir = "{dir}/se/{name}" else dir = "{dir}/es/{name}" end dir.mkdir file = new OFStream.open("{dir}/root.e") var istk = "" if se then istk = " is" write "class ROOT" write "feature id: INTEGER {istk} do Result := 0 end" write "end" file.close for c in classes do file = new OFStream.open("{dir}/{c}.e") write "class {c}[E] " if c.supers.is_empty then write "\tinherit ROOT" else for s in [c.supers.first] do write "\tinherit {s}[E]" end write "\t\tredefine id end" write "feature" write "\tid: INTEGER {istk} do Result := {c.id} end" write "end" file.close end file = new OFStream.open("{dir}/app{name}.e") write "class APP{name.to_upper}" if se then write "insert ARGUMENTS" end write "create make" write "feature" if se then write "\tmake{istk}" else write "\tmake(args: ARRAY[STRING]){istk}" end write "\t\tlocal" write "\t\t\ta: {classes.first}[ROOT]" write "\t\t\tb: {classes.first}[ROOT]" write "\t\tdo" write "\t\t\tcreate \{{classes.last}[ROOT]\} a" write "\t\t\tcreate \{{classes.first}[ROOT]\} b" for c in classes do write "\t\t\tif a.id > 0 then create \{{c}[ROOT]\} a end" end write "\t\t\ttest(b, b, 10, -100)" write "\t\t\ttest(a, a, {loops}, 0)" write "\t\tend" write "\ttest(a: {classes.first}[ROOT]; b: {classes.first}[ROOT]; l: INTEGER; start: INTEGER){istk}" write "\t\tlocal" write "\t\t\to: {classes.first}[ROOT]" write "\t\t\tto: {classes[middle]}[ROOT]" write "\t\t\ti: INTEGER" write "\t\t\tj: INTEGER" write "\t\t\tx: INTEGER" write "\t\t\tloops: INTEGER" write "\t\tdo" write "\t\t\to := a" write "\t\t\tx := start" write "\t\t\tloops := l" write "\t\t\tfrom i := 0 until i>=loops loop" write "\t\t\t\tfrom j := 0 until j>=loops loop" var test if dry then test = "" else write "\t\t\t\t\tto ?= o" test = "to /= Void and then " end write "\t\t\t\t\tif {test}x >= 0 then" if check then write "\t\t\t\t\tx := x + 1" write "\t\t\t\t\telse x := x - 1; o := b end" write "\t\t\t\t\tj := j + 1" write "\t\t\t\tend" write "\t\t\t\ti := i + 1" write "\t\t\tend" write "\t\t\tprint(x.out)" write "\t\tend" write "end" file.close end var count = false end var g = new Generator var outdir = args.first var name = args[1] var use_interfaces = true if args.length > 2 then g.dept = args[2].to_i if args.length > 3 then use_interfaces = false g.genhier g.writenit(outdir, name) g.writejava(outdir, name, use_interfaces) g.writecsharp(outdir, name, use_interfaces) g.writescala(outdir, name, use_interfaces) g.writecpp(outdir, name) g.writee(outdir, "{name}_se", true) g.writee(outdir, name, false)