Constructor not found - squeak

I'm trying to implement a new class in Squeak, and for some reason when I run a test I get a MessageNotUnderstood error, even though the message is defined.
Class code:
Object subclass: #ClassAnalyzer
instanceVariableNames: 'theClasses'
classVariableNames: ''
poolDictionaries: ''
category: 'OOP3'!
!ClassAnalyzer methodsFor: 'initialize-release' stamp: 'NK 11/30/2009 22:50'!
initialize: setOfClasses
theClasses := setOfClasses.! !
!ClassAnalyzer methodsFor: 'initialize-release' stamp: 'NK 11/30/2009 22:49'!
newWith: input
[input isKindOf: Collection]
ifFalse: [^ClassAnalyzer new: input].
^ClassAnalyzer new: (input asSet).! !
And here's the test I ran:
| abcd z |
z:=1class.
abcd:= ClassAnalyzer newWith: z.
Any idea what I'm doing wrong?
My current theory is that since when you invoke a constructor there's no object yet, so it should be a bit different (maybe there should be a predefined function of the same name in Object or protoObject), but if that's the deal, then how would one go about defining a none standard named constructor without changing Object?

You should define the constructor on the class side. In the browser there are three buttons [ instance ][ ? ][ class ], click on the class button to add methods on the class side. Don't forget to switch back to the instance side after you are done.

Note that this line of yours is likely to contain a mistake:
[input isKindOf: Collection]
ifFalse: [^ClassAnalyzer new: input]
Instead, you probably want to call ifFalse on a boolean, so you used the wrong sort of braces. Instead do:
(input isKindOf: Collection)
ifFalse: [^ClassAnalyzer new: input]
The rest was covered by Adrian (newWith: should be on the class side. In Java parlance, you'd call it a static method).

Related

Clang AST matching method call on class, derived class or typedef to either

I have a matcher that works perfectly for matching operator() calls on instances of a class or classes derived from that class. For example, it matches the final line of:
class MyBase { void operator()(...) {} };
MyBase b;
b(parameters);
using a matcher like:
const auto MyBaseExpr =
expr(hasType(cxxRecordDecl(isSameOrDerivedFrom("::MyBase"))));
Finder->addMatcher(traverse(
TK_AsIs, cxxOperatorCallExpr(
hasOverloadedOperatorName("()"),
hasArgument(0, anyOf(MyBaseExpr, MyOtherBaseExpr)),
hasAnyArgument(...),
this);
But I'd also like to be able to match such calls on instances of typedefs for the base or derived types like in the last line below:
typedef MyBase MyTypedef;
MyTypedef t;
t(parameters);
and I can't seem to fathom the correct way to specify this match. Attempting to use hasUnqualifiedDesugaredType rather than hasType doesn't work since it works on a type rather than a Decl and if I try to do more matching with the type then I can't use isSameOrDerived which returns a Matcher<CXXRecordDecl>. A similar problem occurs when trying to use hasCanonicalType:
.../RedundantStringCStrCheck.cpp:193:40: error: invalid initialization of reference of type ‘const clang::ast_matchers:
:internal::Matcher<clang::QualType>&’ from expression of type ‘clang::ast_matchers::internal::BindableMatcher<clang::Decl>’
193 | expr(hasCanonicalType(cxxRecordDecl(isSameOrDerivedFrom("::MyBase"))));
MyTypedef is defined from MyBase so its Canonical Type should be MyBase. More information about canonical type: https://clang.llvm.org/docs/InternalsManual.html#canonical-types
This is the example from LibASTMatchersReference , it uses hasType().
Thien Tran provided the pointer which led me to the right answer. Here's my original expression
const auto MyBaseExpr =
expr(hasType(cxxRecordDecl(isSameOrDerivedFrom("::MyBase"))));
I was trying to use:
const auto MyBaseExpr =
expr(hasCanonicalType(cxxRecordDecl(isSameOrDerivedFrom("::MyBase"))));
but the description of hasCanonicalType in LibASTMatchersReference shows that it takes and returns Matcher<QualType> yet cxxRecordDecl has type Matcher<Decl>, so this did not compile.
The mismatch of types can be corrected by inserting a call to hasDeclaration. It's then also necessary to keep the call to hasType in order to turn the Matcher<QualType> result of hasCanonicalType back into something that can be passed to expr.
After all that I ended up with:
const auto MyBaseExpr =
expr(hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom("::MyBase"))))));
which seems to work perfectly.

Extending XFeatureCall scope

This has been puzzling me for a while... I have done research, tried lots of things but failed miserably. The time has come to ask here.
My grammar has this rule to define types:
MyTypeDeclaration returns XExpression:
=>({MyTypeDeclaration} type=JvmTypeReference name=ValidID '(')
(params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)?
')' block=XBlockExpression
;
Of course, in the inferrer, I map it to a class (with a supertype MySupertype to differentiate from other Java classes)
members += f.toClass(f.fullyQualifiedName) [
superTypes += typeRef(MySupertype)
...
members += f.toConstructor [
for (p : f.params)
parameters += p.toParameter(p.name, p.parameterType)
body = f.block
]
...
]
What I need is to invoke this class as a function, e.g. using XFeatureCall. XFeatureCall::feature is a JvmIdentifiableElement and so is MyTypeDeclaration when mapped (in the compiler I will add a "new" prefix to call the class constructor). However, naturally, XFeatureClass does not include Java classes in its default scope.
So the question is, how to change this behavior? I need to include MyTypeDeclaration instances (or, more generally, Java classes with MySupertype as superclass) in XFeatureClass scope. I looked at the type computer, getLinkingCandidates and al but it looks too arcane for me.
I use version 2.15 as I need GWT...
Please help as I am really stuck at this point...
Thanks,
Martin

Creating a capitalize Method in Dart

I am trying to create a method in dart but have run into a wall. I was looking at how .toUpperCase(); and .toLowerCase(); were done. The method that I am trying to create is .capitalize();
I would like to call this method like this
String hello = "WORLD".capitalize(); //World
Here is the code I have so far
String capitalize() {
return this.codeUnitAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
When running String hello = "WORLD".capitalize(); I get the following error
[38;5;124m[2015-6-4 11:37:13.011] Class 'String' has no instance method 'capitalize'.
NoSuchMethodError: method not found: 'capitalize'
Receiver: "WORLD"
Arguments: [][0m
I know i can call a function like String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
But would much rather keep string Manipulation calls the same.
Thanks and I appreciate any help:)
You cannot extend the String class like you want. Just use it like this:
capitalize("WORLD");
Yes, not like JS, you can't just change any class in Dart. You can extend it only. E.g. you can create MyString class with capitalize method. But I don't think you want it. Just make some StringUtils.dart library with method capitalize
Since dart is more common now, there are a lot more packages available at pub.dartlang.org.
I found a nice dart package for different operation on strings. It also contains a capitalize method.
https://pub.dartlang.org/packages/basic_utils
Simply add the dependency :
dependencies:
basic_utils: ^1.0.3
Usage :
StringUtils.capitalize("helloworld"); // helloworld => Helloworld
It also contains other usefull methods :
camelCaseToUpperUnderscore
camelCaseToLowerUnderscore
isAscii
isNullOrEmpty ...
if this is still a problem, you can simple use this dependecy:
dependencies:
text_tools: ^0.0.2
Is simple to use, here is an example:
//This will put the first letter in UpperCase, will print 'Name'
print(TextTools.toUppercaseFirstLetter(text: 'name'));

Getting the parameters of a method call from a clang match callback

I'm adapting the Clang tool-template (as described here) to search for a particular method call in my code. In order to later rewrite that call, I would like to get the type of the parameters the method was called with, as well as the type of the object the method was called on.
I managed to find a matcher that calls back the following:
class AddListenerPrinter : public MatchFinder::MatchCallback
{
public :
virtual void run(const MatchFinder::MatchResult &Result) {
if (const auto *FS = Result.Nodes.getNodeAs<clang::MemberExpr>("ListeningBound"))
{
FS->dump();
}
}
};
which prints out:
MemberExpr 0x7fb05b07b948 '<bound member function type>' .addListener 0x7fb05b077670
`-MemberExpr 0x7fb05b07b918 'class MyCore' lvalue ->mCore 0x7fb05b078e30
`-CXXThisExpr 0x7fb05b07b900 'class MyComponent *' this
Now I can't find any way to retrieve the type of the object the method was called on (here class MyCore) or the type of the method argument (here class MyComponent).
How can I do this?
I found the answer by browsing the code of the existing matchers.
Using matcher = memberCallExpr( callee(methodDecl(hasName("addListener"))) )
I was able to retrieve a CXXMemberCallExpr node. Then getting the type of the object the method was called on:
// FS is the CXXMemberCallExpr
// Prints out the type of x in x.method()
llvm::outs() << FS->getRecordDecl()->getName();
and the method parameters are accessible through FS->getArg(n).
Bottom line is: Find the CXX object that contains what you're looking for first (e.g. which class has methods to access function arguments?), then find the matcher that will return the same type of object in ASTMatchers.h.
Hoping this can help anybody else with the same problem.

in Dart, problems when attempting to "register" sub-class with super-class

I wish to have the sub-classes of a super-class "registered" by an arbitrary name - whenever I declare a sub-class I wish to also have it entered into the super-class.sub Map.
Is there any way to accomplish this outside of main()?
// base class
class Mineral{
final String formula;
static Map<String,Mineral> sub = {}
Mineral( this.formula );
}
// sub class - declare and register
class Mica extends Mineral{
Mica( String formula ) : super( formula );
}
Mineral.sub['mica'] = Mica; // oops!
when I run this, I get
Error: line 10 pos 1: unexpected token 'Mineral' Mineral.sub['mica'] = Mica;
assuming that executable code is not allowed outside main().
cannot put within the super-class since other sub-classes may declared later, outside the library.
Dart has no way to run code as part of a library being loaded.
Executable code can only be put inside methods, or in field initializers, and static field initializers are lazy so they won't execute any code until you try to read them.
This is done to ensure quick startup - a Dart program doesn't have to execute any code before starting the main library's "main" method.
So, no, there is no way to initialize something that isn't constant before main is called.
Either
Mineral.sub['mica'] = new Mica();
or
static Map<String,Type> sub = {};
When you assign Mica you assign the Type Mica. new Mica() is an instance of Mica that is of the kind Mineral and can be assigned to the map you declared.
edit
Maybe you want to initialize the sub map:
static Map<String,Mineral> sub = {'mica': new Mica()};
hint: the semicolon is missing in this line in your question.

Resources