#> x = ArrayList.new()
#> x.add(Integer.new(1))
#> puts x.get(0).class()
=> class java.lang.Integer
#> x = List(ArrayList.new())
#> x.add(Integer.new(1))
#> puts x.get(0).class()
=> class java.lang.Object
--
You received this message because you are subscribed to the Google Groups "The Mirah Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mirah+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
If I had to guess, I think the problem is that casts currently drop the generic inference information.
I'm not sure why you would use a cast that way though. Maybe to force an inferred return type?
Also, I would be interested in seeing what you've got for a translator. Even if it's currently just a collection of regexes.
--
class JavaToMirah
AllPrims = 'byte|short|int|long|char|float|double|boolean'
#
FinalFix = [/(private|public|protected) static final (.+?) (.+?) = (.+?);/, 'def self.\3():\2; \4; end']
#Variable Type
KlsVarFix = [/(\x28|,|, |\t)([^\x28\x29\<\>\t ,+":!=][^\x28\x29\t ,+":!=]*) ([^\x28\x29\t ",+:!=]+)(\x29|,)/, '\1\3:\2\4']
#Instance Variable Declarations
##@@deklare[mtch[4]] = {type: mtch[2], extType: mtch[3], ln: @line, mln: declareFixer(@mline.sub(*(DeclareFixes[i]))), cmt: @comment}
DeclareFix = [/(private|public|protected) ([A-Za-z][A-Za-z0-9_]*)() ([a-z][A-Za-z0-9_]*);/, '@\4 = \2(nil)']
DeclareArrayFix = [/(private|public|protected) ([A-Za-z][A-Za-z0-9_]*)(\[\]) ([a-z][A-Za-z0-9_]*);/, '@\4 = \2[0]']
NewDeclareFix = [/(private|public|protected) ([A-Z][^\<\>\s,;]*?)() ([^\s]+?) = new ([A-Z][A-Za-z0-9_]*?)(.*?);/, '@\4 = \5.new\6;']
PrimDeclareFix = [/(private|public|protected) (#{AllPrims})() ([^\s]+?) = (.*?);/, '@\4 = \5;']
ComplexDeclareFix = [/(private|public|protected) ([A-Za-z][^\<\>\s,]*?)(<.+?>) (.+?) = new ([A-Za-z][^\<\> ,]*?)(<.+?>)(.*?);/, '@\4 = \2(\5.new\7); # \3 ##Fix Generics by Hand']
#Instance Variable Assignment
ThisFix = [/([^A-Za-z0-9_.]|^)this\./, '\1@']
#Methods
StaticMethodFix = [/(private|public|protected) static ([a-zA-Z][^\<\> ]*?) (.+?)\x28([^\x29]*)\x29.*$/, 'def self.\3(\4):\2']
MethodFix = [/(private|public|protected) (.+?) ([a-z][A-Za-z0-9_]*?)\x28([^\x29]*)\x29.*$/, 'def \3(\4):\2']
InitializeFix = [/(private|public|protected) ([A-Z].*?)\x28([^\x29]*)\x29.*$/, 'def initialize(\3):void']
#General Java to Mirah Syntax
KlassNewFix = [/new ([A-Za-z][A-Za-z0-9]+)(\x28.*?\x29)/, '\1.new\2']
CastFix = [/\x28([A-Za-z][A-Za-z0-9_]+)\x29 ([A-Za-z][^\s;]*)/, '\1(\2)']
LocalVarFix = [/([A-Za-z][A-Za-z0-9_]+) ([A-Za-z][^\s]*) = (.+?);/, '\2 = \1(\3)']
LocalNewArrayFix = [/([A-Za-z][A-Za-z0-9_]+)\[\] ([A-Za-z][^\s]+) = new ([a-zA-Z][A-Za-z0-9_]*?)\[(.+?)\];/, '\2 = \3[\4]']
LocalArrayFix = [/([A-Za-z][A-Za-z0-9_]+)\[\] ([A-Za-z][^\s]+) = ([^n].+?);/, '\2 = \1[].cast(\3)']
NullToNilFix = [/([^A-Za-z0-9_.])null([^A-Za-z0-9_.])/, '\1nil\2']
TryFix = [/^try$/, 'begin']
CatchFix = [/^catch( .+)$/, 'rescue #\1']
TernaryFix = [/= (.+?) \? (.+?) : (.+?);/, '= ((\1) ? (\2) : (\3))']
#Loops
ForLoop = /^for \x28([a-zA-Z][A-Za-z0-9_]*) ([a-z][A-Za-z0-9_]*) = (\S+?); ([a-z][A-Za-z0-9_]*) (\>|\<) (\S+?); (.+?)\x29$/
ForEachFix = [/^for \x28([a-zA-Z][A-Za-z0-9_]*) ([a-z][A-Za-z0-9_]*) : (.+?)\x29$/, '\3.each do |\2:\1|']
ForTimesFix = [/^for \x28int ([a-z][A-Za-z0-9_]*) = 0; ([a-z][A-Za-z0-9_]*) < ([^\s;]+); ([a-z][A-Za-z0-9_]*)\+\+\x29$/, '\3.times do |\1:int|']
#Fix Packs :)
OnePassFixes = [FinalFix, StaticMethodFix, MethodFix, TernaryFix, TryFix, CatchFix, ForEachFix, ForTimesFix]
MultiPassFixes = [KlsVarFix, KlassNewFix, CastFix, LocalVarFix, LocalNewArrayFix, LocalArrayFix, ThisFix, NullToNilFix]
DeclareFixes = [DeclareFix, DeclareArrayFix, PrimDeclareFix, NewDeclareFix, ComplexDeclareFix]
@@klass = nil
@@deklare = {}
@@deklared = []
@@konstants = []
@@inComment = false
def self.setClass(title)
@@klass = title
end
def self.addObjVar(var, info)
@@deklare[var] = info
end
def initialize(par = nil, prvLine = nil, nxtLine = nil, chil = nil, lin = '', mlin = '', cmnt = '')
@line = lin
@mline = mlin
@comment = cmnt
@parent = par
@prv = prvLine
@nxt = nxtLine
@child = chil
@initializer = false
end
def insert(lin = '', mlin = '', cmnt = '')
ins = JavaToMirah.new(@parent, @prv, self, nil, lin, mlin, cmnt)
@prv.newLine(ins) unless @prv.nil?
@parent.setChild(ins) unless (topLevel? or !@prv.nil?)
@prv = ins
end
def line()
@line
end
def mline()
@mline
end
def lineBlank?()
@line.strip.gsub(/\s/, "").empty?
end
def prevLine()
@prv
end
def nextLine()
@nxt
end
def child()
@child
end
def hasChild?()
!@child.nil?
end
def parent()
@parent
end
def topLevel?()
@parent.nil?
end
def klassLevel?()
return false if topLevel?
@parent.topLevel?
end
def initMethod?()
return false if topLevel?
return @initializer if klassLevel?
@parent.initMethod?
end
def addChar(c)
#puts c
#puts @line
@line += c
end
def addChild()
@child = JavaToMirah.new(self)
return @child
end
def setChild(chil)
@child = chil
end
def exitBlock()
@parent.newLine(self)
@prv.delNext unless @prv.nil?
@parent.setChild(JavaToMirah.new()) if @parent.child == self
@prv = @parent
@parent = @prv.parent
end
def newLine(nline = nil)
if nline.nil?
@nxt = JavaToMirah.new(@parent, self)
else
@nxt = nline
end
return @nxt
end
def delNext()
@nxt = nil
end
def cleanLine()
@line = @line.strip.gsub(/\s+/, " ")
end
def printAll(tabs = 0)
cleanLine()
puts (" " * tabs) + @line
@child.printAll(tabs + 1) unless @child.nil?
@nxt.printAll(tabs) unless @nxt.nil?
end
def printAllMirah(tabs = 0)
cleanLine()
indent = " " * tabs
out = @mline.empty? ? "" : @mline
(out = (out + '#' + @comment).lstrip) unless @comment.empty?
out = indent + out
puts out unless out.strip.empty?
if hasChild?
@child.printAllMirah(tabs + 1)
puts indent + "end" + (klassLevel? ? "\n" + indent : '') if useEnd?
end
@nxt.printAllMirah(tabs) unless @nxt.nil?
end
def toMirah()
if @line =~ /class ([A-Z][a-zA-Z0-9]+)/
JavaToMirah.setClass(@line.match(/class ([A-Z][a-zA-Z0-9]+)/)[1])
@mline = "class " + @@klass
elsif @line =~ /\/\*/
@@inComment = true
elsif @line =~ /\*\//
@@inComment = false
elsif @@inComment
# Ignore
else
@mline = @line
if @mline =~ /\/\//
mtch = @mline.match(/(.*?)\/\/(.*?)$/)
@mline = mtch[1]
@comment = mtch[2]
end
if @mline =~ FinalFix[0]
kon = @mline.match(FinalFix[0])[3]
@@konstants << kon unless @@konstants.include?(kon)
end
if klassLevel?
DeclareFixes.size.times do |i|
next if (@mline.empty? or !(@mline =~ DeclareFixes[i][0]))
mtch = @mline.match(DeclareFixes[i][0])
@@deklare[mtch[4]] = {type: mtch[2], extType: mtch[3], ln: @line, mln: declareFixer(@mline.sub(*(DeclareFixes[i]))), cmt: @comment}
@mline = ""
end
end
OnePassFixes.each {|fix| @mline = @mline.sub(*fix) if @mline =~ fix[0] }
MultiPassFixes.each {|fix| @mline = @mline.sub(*fix) while @mline =~ fix[0] }
if ((@mline =~ InitializeFix[0]) and ((@mline.match(InitializeFix[0])[2] == @@klass) and !@@klass.nil?))
@initializer = true
@mline = @mline.sub(*InitializeFix)
end
if @mline =~ /@([a-z][A-Za-z0-9_]*?) = (.+?);/
mtch = @mline.match(/@([a-z][A-Za-z0-9_]*?) = (.+?);/)
@@deklared << mtch[1]
end
end
@child.toMirah() unless @child.nil?
@nxt.toMirah() unless @nxt.nil?
if @initializer
tmp = @child
@@deklare.keys.each do |var|
next if @@deklared.include?(var)
info = @@deklare[var]
tmp.insert(info[:ln], info[:mln], info[:cmt])
end
elsif !initMethod?
@@deklare.keys.each do |var|
varfind = /(^|[^@A-Za-z0-9_])#{var}([^A-Za-z0-9_]|$)/
while @mline =~ varfind
@mline = @mline.sub(varfind, "\\1@#{var}\\2")
end
end
end
@@konstants.each do |var|
varfind = /(^|[^@A-Za-z0-9_])#{var}([^A-Za-z0-9_\x28]|$)/
while @mline =~ varfind
@mline = @mline.sub(varfind, "\\1#{var}()\\2")
end
end
@mline.sub!(/;[\s]*$/, '')
end
def declareFixer(str)
return str unless str =~ /= (#{AllPrims})\x28nil\x29/
out = ''
#puts str
#p str.match(/(float|double)\x28nil\x29/)
out = str.sub(/(byte|short|int|long|char)\x28nil\x29/, '\1(0)') if str =~ /(byte|short|int|long|char)/
out = str.sub(/(float|double)\x28nil\x29/, '\1(0.0)') if str =~ /(float|double)/
out = str.sub(/boolean\x28nil\x29/, 'false') if str =~ /boolean/
#puts out
return out
end
def forFixer(str)
# placeholder for more advanced for loops
return str
end
def useEnd?()
return true if (@nxt.nil? or !(@mline =~ /^(if|elsif|begin)/))
if @mline =~ /^(if|elsif)/
return (@nxt.mline =~ /^(elsif|else)( |$)/ ? false : true)
end
if @mline =~ /^begin/
return (@nxt.mline =~ /^rescue( |$)/ ? false : true)
end
end
end
test = <<-FOO
public class SomeClass {
private static final int PAD_BOTTOM = 2;
private static final String SPLITTER = " ";
public int avar;
public int bvar;
public int cvar;
public SomeClass(int var, String var2) {
this.avar = var; // Test 1
// Test 2
}
public int getVar() {
return avar;
}
}
FOO
code = ((ARGV.size > 0) ? File.open("java2mirah\\" + ARGV[0] + '.java') { |f| f.read } : test)
out = JavaToMirah.new()
tmp = out
cmmnt = false
quotes = ''
lc = ''
insideLst = ['(', ')', '{', '}', '[', ']']
insideKey = {'(' => :p1, ')' => :p1, '{' => :p2, '}' => :p2, '[' => :p3, ']' => :p3}
insideRev = {p1: ['(', ')'], p2: ['{', '}'], p3: ['[', ']']}
inside = {p1: false, p2: false, p3: false}
code.each_char do |c|
cmmnt = true if ((lc + c) == '/*')
cmmnt = false if ((lc + c) == '*/')
if insideLst.include?(c)
inside[insideKey[c]] = true if (c == insideRev[insideKey[c]][0])
inside[insideKey[c]] = false if (c == insideRev[insideKey[c]][1])
end
if ((c == '{') and !cmmnt)
tmp = tmp.addChild
elsif ((c == '}') and !cmmnt)
tmp.exitBlock
elsif ((c == "\n") and !inside[:p1])
tmp.cleanLine()
(tmp = tmp.newLine) unless tmp.lineBlank?
else
tmp.addChar(c) unless c.nil?
end
lc = c
end
out.printAll
out.toMirah
out.printAllMirah
Does rescue work with returned exceptions yet?
I think in the documentation says something like "rescue Exception => e". Does that syntax still work?
catch (Exception e)
rescue # e:Exception
rescue |e:Exception|
rescue Exception => e
If I had to guess, I think the problem is that casts currently drop the generic inference information.
I'm not sure why you would use a cast that way though. Maybe to force an inferred return type?
private Map<String, Integer> myMap = new HashMap<String, Integer>();
myMap = Map(HashMap.new()) # <String, Integer> ## Fix Generics by Hand
package test
import java.util.List
import java.util.ArrayList
class TestA
def initialize(str:String):void
@string = str
end
def out():String
@string
end
end
class TestB
def initialize():void
@list = List(ArrayList.new()) # just ArrayList.new() also works
end
def add(tst:TestA):void
@list.add(tst)
end
def get(i:int):TestA
return TestA(@list.get(i)) if @list.size > i # Does not work without explicit cast to TestB
return TestA(nil)
end
end
x = TestB.new()
x.add(TestA.new("Test 1"))
x.add(TestA.new("Test 2"))
puts x.get(1).out
One thing to note is that the mirah version that my netbeans plugin is a little out of date, so issues like you mention with casts to List might actually be fixed in the latest Mirah. It is on my todo list to update it, but there have been quite a few changes, that make updating it a little involved.
First off, Java has several implementations of Lists and Maps. Often
very fine grained details separate them ... But we can categorically talk
about "listy things" and "mappy things", knowing that all Lists can
index things at a given offset, and that all Maps find things through
keys.
The category interface is often preferred in large bodies of code to make it more
maintainable.
JAVA: InterfaceClass test = (InterfaceClass) (new ImplementationClass());
MIRAH; test = InterfaceClass(ImplementationClass.new())
These two accomplish exactly the same things.
To go back to our example, Mirah pretty well only implements the above like so:
HashMap<Object, Object>, ArrayList<Object>
Fortunately, there are convenience casts possible in iterator blocs, etc.
list = ArrayList.new()
list.add(ItemClass.new())
list.each do |item:ItemClass|
item.item_method()
end
There is also kind of a third thing that sometimes happens. Suppose
you try to stuff an implicit type into that array. Mirah will
transparently supply a constructor call to the appropriate object
wrapper for the implicit type.
Thus the implicit type will get wrapped with an object which can
meaningfully be placed in the ArrayList<Object>. I point this out
because when you fetch your data out, you will have an object that you
must unpack. For example, our loop would change to:
list.each do |item:Integer|
i = item.intValue()
puts i
end
I hope this insight will help you as you develop your code translator
and enjoy your Mirah programming more.
Regards,
-S-
On Tuesday, December 8, 2015 at 11:55:36 AM UTC-8, Steve Hannah wrote:One thing to note is that the mirah version that my netbeans plugin is a little out of date, so issues like you mention with casts to List might actually be fixed in the latest Mirah. It is on my todo list to update it, but there have been quite a few changes, that make updating it a little involved.
Do you have to fork mirah and add your own hooks and whatnot for it to work with NBMirah? Or do you mean you have to make changes just to the plugin to get it working with a different version? Is there no way for it to use external Mirah?
I kinda want to go through your code at some point and see if I can get it to stop adding "end" when you hit enter at the end of a one line def statement or one line if statement.
--
You received this message because you are subscribed to the Google Groups "The Mirah Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mirah+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.