Why does this happen with ArrayList cast as List?

30 views
Skip to first unread message

Raum Dellamorte

unread,
Dec 8, 2015, 2:45:52 PM12/8/15
to The Mirah Programming Language
#> 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

In java, people tend to make a List variable and assign an ArrayList to it.  They, of course, have working Generics.  Anyway, not sure why this happens, but it's a mild frustration.  Working around it means more code.  When Mirah is "finished", it should always mean writing less, simpler, and more readable code.

On a separate note, I'm writing a ruby script to convert Java to Mirah because Steve's NetBeans plugin,  in my experience, seems to work better when all the code is in Mirah, at least with Maven projects, and I've been following LWJGL tutorials with downloadable java files for the tedious code so I have to rewrite all that java in mirah.  While trans-coding by hand is good exercise, it is tedious, hence said script.  Right now, it just means a lot less to fix by hand.  It's mostly a lot of regex.  If anyone is interested, I'll put it on github sooner rather than later.

Steve Hannah

unread,
Dec 8, 2015, 2:55:36 PM12/8/15
to mi...@googlegroups.com
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.

--
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.



--
Steve Hannah
Web Lite Solutions Corp.

Nick Howard

unread,
Dec 8, 2015, 3:12:18 PM12/8/15
to mi...@googlegroups.com

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.

--

Raum Dellamorte

unread,
Dec 8, 2015, 3:36:42 PM12/8/15
to The Mirah Programming Language
I'll put it on github once I get through my current set of java files that I'm using to debug an refine it, but it's already very useful.

Current code:

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


Raum Dellamorte

unread,
Dec 8, 2015, 4:39:00 PM12/8/15
to The Mirah Programming Language
Does rescue work with returned exceptions yet?

I think in the documentation says something like "rescue Exception => e".  Does that syntax still work?

J. Scott Kasten

unread,
Dec 8, 2015, 5:55:40 PM12/8/15
to mi...@googlegroups.com, Nick Howard
Yeah, second that on the translator. I think a good bit of interest will come about as it becomes "ready".

-s-
--
Sent from my Android device.

J. Scott Kasten

unread,
Dec 8, 2015, 6:19:21 PM12/8/15
to mi...@googlegroups.com, Raum Dellamorte
I can say for sure that it works well in 0.1.3 as I use it extensively in about 50,000 lines of Android code. Unfortunately, I was close to release when 0.1.4 became available and it would have necessitated some code changes so that upgrade didn't make the last development cycle.

Shameless plug:

https://play.google.com/store/apps/details?id=com.UVS.Innovations.organizer.ToDo

It's best described as an alternative to Asana or Evernote.

In the next round, I plan to shake down 0.1.4 really well. Or 0.1.5...nudge nudge wink wink..... :-)

-s-



On December 9, 2015 5:39:00 AM GMT+08:00, Raum Dellamorte <elemen...@gmail.com> wrote:
Does rescue work with returned exceptions yet?

I think in the documentation says something like "rescue Exception => e".  Does that syntax still work?


Raum Dellamorte

unread,
Dec 8, 2015, 7:00:49 PM12/8/15
to The Mirah Programming Language, elemen...@gmail.com
Right now it changes
catch (Exception e)
to
rescue # e:Exception

cause I wasn't sure how it worked.

What I expect to see is
rescue |e:Exception|
because that's what looks right for mirah, but now I can correct it to
rescue Exception => e

Thanks!

Raum Dellamorte

unread,
Dec 8, 2015, 7:20:22 PM12/8/15
to The Mirah Programming Language
On Tuesday, December 8, 2015 at 12:12:18 PM UTC-8, Nick Howard wrote:

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?


 I have only really learned Java through learning Mirah, but I see this all the time:
private Map<String, Integer> myMap = new HashMap<String, Integer>();

so my prog currently converts that to:
myMap = Map(HashMap.new()) # <String, Integer> ## Fix Generics by Hand

However, it looks like I should drop the cast even though the original java does the cast but I'm not sure how that will effect the expected use of that variable.  I put the expected types in a comment so that you can come up with a workaround by hand.  But if I drop the cast maybe it would just work?  It's just that the inference seems like it can be tricky at times with generics.  I'm not to the point of experimentation in the project I'm doing this for yet so I'd have to write a test project and I don't want to do that right now :P

Raum Dellamorte

unread,
Dec 8, 2015, 7:48:44 PM12/8/15
to The Mirah Programming Language
I don't remember this working so well in the past but it works now.

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

Prints "Test 2" just as it should.

You get used to old bugs and it's hard to change your ways when they get fixed :)

Raum Dellamorte

unread,
Dec 8, 2015, 8:04:35 PM12/8/15
to The Mirah Programming Language
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.

J Scott Kasten

unread,
Dec 8, 2015, 9:47:14 PM12/8/15
to Mirah Mailing List
Since you mentioned that you were learning java through mirah, I
thought to take just a moment to explain in more detail what you're
seeing happen here. It's a little confusing since there are two
different processes involved, but the clarity would be helpful for
you. Comments follow.

On Wed, Dec 9, 2015 at 8:20 AM, Raum Dellamorte <elemen...@gmail.com> wrote:
>
> I have only really learned Java through learning Mirah, but I see this all
> the time:
> private Map<String, Integer> myMap = new HashMap<String, Integer>();

First off, Java has several implementations of Lists and Maps. Often
very fine grained details separate them, such as whether this thing
has locking primitives built in to allow concurrent editing between
multiple process threads or isn't thread safe at all, or how memory
efficient the backing store is, etc... 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. It's purely the programmer's choice to reference things through
the category interface or the explicit type interface. The category
interface is often preferred in large bodies of code to make it more
maintainable. We usually don't care what the source of the object is,
and often times it can come from more than one source. We just expect
to do simple stuff like index the List or Map through most of the code
body.

To that extend, Mirah and Java are nearly identical once you get past
the syntax differences.

JAVA: InterfaceClass test = (InterfaceClass) (new ImplementationClass());

MIRAH; test = InterfaceClass(ImplementationClass.new())

These two accomplish exactly the same things.

> so my prog currently converts that to:
> myMap = Map(HashMap.new()) # <String, Integer> ## Fix Generics by Hand
>
> However, it looks like I should drop the cast even though the original java
> does the cast but I'm not sure how that will effect the expected use of that
> variable. I put the expected types in a comment so that you can come up
> with a workaround by hand.

The second process here is the implementation of generics. The point
of the generics in Java could most simply be described as... "The list
contains what exactly?" Java basically would apply some annotations
to make sure you only try to stuff xyz's into that list.

Mirah only kind of sort of has generics. Basically, except in very
limited cases that have been documented in this forum in the past,
Mirah implements all generic annotations as objects.

To go back to our example, Mirah pretty well only implements the above like so:

HashMap<Object, Object>, ArrayList<Object>

Those are your one and only choices. The important part of this being
that when you retrieve your data from the List or Map, you usually
have to cast it to something useful. 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.

In other words, try doing this:

list.add( 1 )

And Mirah will actually do:

list.add( Integer.new(1) )

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-

Raum Dellamorte

unread,
Dec 9, 2015, 4:07:54 AM12/9/15
to The Mirah Programming Language
On Tuesday, December 8, 2015 at 6:47:14 PM UTC-8, J Scott Kasten wrote:
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.
Yes, no problem there.  The fine grained details with Thread safety and whatnot I didn't know but makes immediate sense.
 
The category interface is often preferred in large bodies of code to make it more
maintainable.
And I get that.  I think my issue is more how to go about it in Mirah.  You can have ArrayList<SpecificType> but casting that to List gets you List<Object>, and maybe I've been doing it wrong, but I've had problems with my code complaining about not being able to be cast from Object back to what it's supposed to be.

JAVA:   InterfaceClass  test  =  (InterfaceClass) (new ImplementationClass());

MIRAH;   test = InterfaceClass(ImplementationClass.new())

These two accomplish exactly the same things.
They're supposed to, but as Nick pointed out, casting drops the Generic class in Mirah.

I also get that Generics are a workaround for the difficulties arising with Strong Typing.  Java doesn't like not knowing exactly what kind of object it's dealing with, and if not for Generics, you might have to create a different List class for every object.  That's impractical.  

To go back to our example, Mirah pretty well only implements the above like so:

HashMap<Object, Object>,  ArrayList<Object>
My experiment shows that you can hold on to the Generic type as long as you don't cast it as it's superclass.  So HashMap<String, SomeClass> works, but you cast it to a Map and you get Map<Object, Object> and you have to hope you can cast back up to String and SomeClass without the compiler insisting that you can't.  I need to experiment more to figure out the best course of action.
 
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
Yes, and it's fine when that works.  I'm just convinced that it doesn't always work.  I just can't remember the circumstances and I'll have to recreate them to figure it out.  I also used to have a habit of insisting on using Arrays all the time because they have specific type but Java code tends to use Lists with a generic type more often than Arrays because Arrays are more rigid, I think.

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.
And thank you to the Mirah developers for that :)
 
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-

Thanks :)  While I was aware of some of this, you have been helpful.  Input from others helps one to break out of the box one thinks in without knowing it.

Because my translator isn't able to determine types (yet) it wouldn't be easy to make it cast certain things correctly.  At the very least, it will shorten translation time.  When Mirah has better generics and supports 2d Arrays, things will be simpler.

Steve Hannah

unread,
Dec 9, 2015, 11:20:09 AM12/9/15
to mi...@googlegroups.com
On Tue, Dec 8, 2015 at 5:04 PM, Raum Dellamorte <elemen...@gmail.com> wrote:
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 embed the mirahc.jar and mirah.jar files into the plugin.  They are used for everything from syntax highlighting, to parsing/code completion, as well as the actual compiling.  For the most part, I can just upgrade to the latest but three things require care:

1. The syntax highlighting/parsing code I wrote depends on classes that have since been changed.  So I need to rework it.  I think there are actually better more efficient ways to achieve the same.  However this also might require some updates if additional keywords have been added to the grammar.

2. I did some extra work to make macros work better for my purposes.  Macro handling has since changed, so I'll likely have to revisit my changes also.

3. The netbeans module actually uses a "wrapper" that I wrote which first compiles all java as stubs, then compiles the mirah, then compiles the java so that the mirah can depend on the java code and vice versa.  I'll likely have to rework this a bit as some of the Mirah compiler classes have changed since I last did this.

 
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.
Yes.  This is an annoyance.  It might be an easy fix.  I'll look at it today and see what will be involved.

Steve
 

--
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.
Reply all
Reply to author
Forward
0 new messages