org.apache.royale.abc.semantics.Trait Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compiler Show documentation
Show all versions of compiler Show documentation
The Apache Royale Compiler
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.royale.abc.semantics;
import java.util.HashMap;
import java.util.Vector;
import org.apache.royale.abc.ABCConstants;
import org.apache.royale.abc.semantics.Metadata;
import org.apache.royale.abc.semantics.Name;
import static org.apache.royale.abc.ABCConstants.*;
/**
* A representation of an individual trait.
*/
public class Trait
{
public static final String TRAIT_CLASS = "class_id";
public static final String TRAIT_DISP = "disp_id";
public static final String TRAIT_FINAL = "final";
public static final String TRAIT_METHOD = "method_id";
public static final String TRAIT_NAME = "name";
public static final String TRAIT_OVERRIDE = "override";
public static final String TRAIT_PUBLIC = "public";
public static final String TRAIT_SLOT = "slot_id";
public static final String TRAIT_TYPE = "type";
public static final String SLOT_VALUE = "value";
/**
* Construct a Trait.
*
* @param kind - the Trait's kind nibble.
*/
public Trait(int kind, Name name)
{
this.kind_byte = (byte)(kind & 0x0F);
this.name = name;
addAttr(TRAIT_NAME, name);
}
/**
* This trait's kind byte. Flags are set in the high nibble of the kind
* byte, but only the lower nibble is stored here.
*
* @see #getFullKindByte()
*/
private byte kind_byte;
/**
* This trait's name. This is also denormalized into the trait's attributes
* as TRAIT_NAME.
*/
private final Name name;
/**
* Attributes of this trait. TODO: This shows its origins in abcasm, should
* be converted to a more type-safe system and an adapter layer added to
* abcasm to translate attribute names to their corresponding trait
* attributes.
*/
HashMap attrs = new HashMap();
/**
* Metadata attached to this trait.
*/
private Vector metaData;
/**
* Add a trait attribute.
*
* @param key - the attribute's name.
* @param value - the attribute's value.
* the attribute must not be present.
*/
public void addAttr(String key, Object value)
{
if (attrs.containsKey(key))
{
throw new IllegalArgumentException("Trait attribute " + key + " cannot be specified twice.");
}
attrs.put(key, value);
}
/**
* @return the low nibble of the kind byte (the actual trait kind).
*/
public byte getKind()
{
return (byte)(kind_byte & 0x0F);
}
/**
* @return the kind byte with its flags set in the high nibble.
*/
public byte getFullKindByte()
{
int result = getKind();
if (hasAttr(TRAIT_FINAL) && getBooleanAttr(TRAIT_FINAL))
result = result | (ABCConstants.ATTR_final << 4);
if (hasAttr(TRAIT_OVERRIDE) && getBooleanAttr(TRAIT_OVERRIDE))
result = result | (ABCConstants.ATTR_override << 4);
if (this.hasMetadata())
result = result | (TRAIT_FLAG_metadata << 4);
return (byte)result;
}
/**
* @return the Trait's name.
*/
public Name getName()
{
return this.name;
}
/**
* Set a trait attribute.
*
* @param attr_name - the attribute's name.
* @param attr_value - the attribute's value.
*/
public void setAttr(String attr_name, Object attr_value)
{
attrs.put(attr_name, attr_value);
}
/**
* Determine whether an attribute is present.
*
* @param attr_name - the attribute's name.
* @return true if the attribute is present.
*/
public boolean hasAttr(String attr_name)
{
return attrs.containsKey(attr_name);
}
/**
* Get an attribute's value.
*
* @param attr_name - the attribute's name.
* @return the value of the specified attribute.
* @pre the attribute must be present.
*/
public Object getAttr(String attr_name)
{
verifyContains(attr_name, null);
return attrs.get(attr_name);
}
/**
* Get a integer attribute's value.
*
* @param attr_name - the attribute's name.
* @return the value of the specified attribute.
* @pre the attribute must be present and must be of Integer type.
*/
public int getIntAttr(String attr_name)
{
verifyContains(attr_name, Integer.class);
return (Integer)attrs.get(attr_name);
}
/**
* Get a Name attribute's value.
*
* @param attr_name - the attribute's name.
* @return the value of the specified attribute.
* @pre the attribute must be present and must be of Name type.
*/
public Name getNameAttr(String attr_name)
{
verifyContains(attr_name, Name.class);
return (Name)attrs.get(attr_name);
}
/**
* Get a boolean attribute's value.
*
* @param attr_name - the attribute's name.
* @return the value of the specified attribute.
* @pre the attribute must be present and must be of Boolean type.
*/
public boolean getBooleanAttr(String attr_name)
{
verifyContains(attr_name, Boolean.class);
return (Boolean)attrs.get(attr_name);
}
/**
* Ensure an attribute is present and of the specified type.
*
* @param attr_name - the attribute's name.
* @param clazz - the required class.
*/
void verifyContains(String attr_name, Class extends Object> clazz)
{
if (!attrs.containsKey(attr_name))
throw new IllegalArgumentException("Required attribute " + attr_name + " not found.");
if (!(null == clazz || null == attrs.get(attr_name) || attrs.get(attr_name).getClass().equals(clazz)))
throw new IllegalArgumentException("Attribute " + attr_name + " must be type " + clazz.getSimpleName());
}
/**
* @param kind_byte the kind_byte to set
*/
public void setKind(int kind_byte)
{
this.kind_byte = (byte)(kind_byte & 0x0F);
}
/**
* @return true if the trait is final.
*/
public boolean isFinal()
{
return ((kind_byte >> 4) & TRAIT_FLAG_final) != 0;
}
/**
* @return true if the trait is an override.
*/
public boolean isOverride()
{
return ((kind_byte >> 4) & TRAIT_FLAG_override) != 0;
}
/**
* @return true if the trait has metadata.
*/
public boolean hasMetadata()
{
// getFullKindByte() ensures the TRAIT_metatdata flag is set.
return this.metaData != null;
}
/**
* @return true if the trait is constant.
*/
public boolean isConst()
{
return getKind() == TRAIT_Const || getKind() == TRAIT_Getter;
}
/**
* @return true if the trait is a class trait.
*/
public boolean isClass()
{
return getKind() == TRAIT_Class;
}
/**
* @return true if the trait is a method trait.
*/
public boolean isMethod()
{
return getKind() == TRAIT_Method;
}
/**
* @return true if the trait is a getter trait.
*/
public boolean isGetter()
{
return getKind() == TRAIT_Getter;
}
/**
* @return true if the trait is a setter trait.
*/
public boolean isSetter()
{
return getKind() == TRAIT_Setter;
}
/**
* @return true if the trait is some type of slot trait.
*/
public boolean isSlot()
{
int tk = getKind();
return tk == TRAIT_Var || tk == TRAIT_Const || tk == TRAIT_Class;
}
/**
* Add a metadata entry to this trait.
*
* @param md - the metadata to add.
*/
public void addMetadata(Metadata md)
{
if (null == this.metaData)
this.metaData = new Vector();
this.metaData.add(md);
}
/**
* Common entry for empty metadata.
*/
private static final Vector emptyMetadata = new Vector();
/**
* @return this trait's metadata.
*/
public final Vector getMetadata()
{
if (this.metaData != null)
return this.metaData;
else
return emptyMetadata;
}
}