use phoron_asm::{
ast::{
JvmInstruction::*, PhoronBaseType::*, PhoronClassOrInterface::*, PhoronDirective::*,
PhoronFieldDescriptor::*, PhoronInstruction::*, PhoronReturnDescriptor::*, *,
},
lexer::Lexer,
parser::Parser,
sourcefile::SourceFile,
};
use std::{error::Error, path::Path};
fn parse
(testfile: P) -> Result>
where
P: AsRef + Copy,
{
let source_file = SourceFile::new(testfile.as_ref()).map_err(|err| Box::new(err))?;
let mut parser = Parser::new(Lexer::new(&source_file));
let program = parser.parse().unwrap_or(PhoronProgram::default());
Ok(program)
}
#[test]
fn test_parse_malign() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/Malign.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "Malign".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Bipush(100)),
JvmInstruction(Invokevirtual {
class_name: "java/lang/Object".to_string(),
method_name: "clone".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/Object".to_string(),
}),
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/Malign.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_fields() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/FieldsDemo.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "FieldsDemo".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![
PhoronFieldDef {
name: "x".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPrivate],
field_descriptor: BaseType(Integer),
init_val: None,
},
PhoronFieldDef {
name: "y".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPrivate],
field_descriptor: BaseType(Double),
init_val: None,
},
PhoronFieldDef {
name: "z".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPrivate],
field_descriptor: ObjectType {
class_name: "java/lang/String".to_string(),
},
init_val: Some(PhoronFieldInitValue::QuotedString("Foo".to_string())),
},
PhoronFieldDef {
name: "PI".to_string(),
access_flags: vec![
PhoronFieldAccessFlag::AccPublic,
PhoronFieldAccessFlag::AccStatic,
PhoronFieldAccessFlag::AccFinal,
],
field_descriptor: BaseType(Float),
init_val: Some(PhoronFieldInitValue::Double(3.14159)),
},
],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(1)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/FieldsDemo.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_hola_mundo() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/HolaMundo.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "HolaMundo".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Hola, Mundo!".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/HolaMundo.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_hello_world() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/HelloWorld.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "HelloWorld".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello, world".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/HelloWorld.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_malign_jasmin() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/MalignJasmin.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "MalignJasmin".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(1)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Bipush(100)),
JvmInstruction(Invokevirtual {
class_name: "java/lang/Object".to_string(),
method_name: "clone".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/Object".to_string(),
}),
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/MalignJasmin.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_privet_mir() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/PrivetMir.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "PrivetMir".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Привет, мир!".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/PrivetMir.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_areturn() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/Areturn.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "Areturn".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "makeIntArray".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ArrayType {
component_type: Box::new(BaseType(Integer)),
}),
},
instructions: vec![
PhoronDirective(LimitLocals(2)),
JvmInstruction(Iload0),
JvmInstruction(Newarray {
component_type: PhoronBaseType::Integer,
}),
JvmInstruction(Areturn),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Bipush(10)),
JvmInstruction(Invokestatic {
class_name: "Areturn".to_string(),
method_name: "makeIntArray".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ArrayType {
component_type: Box::new(BaseType(Integer)),
}),
},
}),
JvmInstruction(Astore1),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/Areturn.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_create_array_of_threads() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/CreateArrayOfThreads.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "CreateArrayOfThreads".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Bipush(10)),
JvmInstruction(Anewarray {
component_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/Thread".to_string(),
},
}),
JvmInstruction(Astore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Instanceof {
check_type: PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/Thread".to_string(),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/CreateArrayOfThreads.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_swap_top_two_items() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/SwapTopTwoItems.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "SwapTopTwoItems".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Iconst1),
JvmInstruction(Iconst2),
JvmInstruction(Swap),
JvmInstruction(Pop),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/SwapTopTwoItems.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_create_matrix_of_int() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/CreateMatrixOfInt.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "CreateMatrixOfInt".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(5)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Bipush(2)),
JvmInstruction(Bipush(3)),
JvmInstruction(Bipush(7)),
JvmInstruction(Multianewarray {
component_type: ArrayType {
component_type: Box::new(ArrayType {
component_type: Box::new(ArrayType {
component_type: Box::new(BaseType(Integer)),
}),
}),
},
dimensions: 3,
}),
JvmInstruction(Astore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Instanceof {
check_type: PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::BaseType(
Integer,
)),
}),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/CreateMatrixOfInt.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_count() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/Count.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "Count".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(4)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Astore1),
JvmInstruction(Bipush(10)),
JvmInstruction(Istore2),
PhoronLabel("Loop".to_string()),
JvmInstruction(Bipush(10)),
JvmInstruction(Iload2),
JvmInstruction(Isub),
JvmInstruction(Invokestatic {
class_name: "java/lang/String".to_string(),
method_name: "valueOf".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Astore3),
JvmInstruction(Aload1),
JvmInstruction(Aload3),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Iinc {
varnum: 2,
delta: -1,
}),
JvmInstruction(Iload2),
JvmInstruction(Ifne {
label: "Loop".to_string(),
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/Count.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_catcher() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/Catcher.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "Catcher".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
PhoronDirective(Catch {
class_name: "java/lang/Exception".to_string(),
from_label: "Label1".to_string(),
to_label: "Label2".to_string(),
handler_label: "Handler".to_string(),
}),
PhoronLabel("Label1".to_string()),
JvmInstruction(New {
class_name: "java/lang/Exception".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Invokespecial {
class_name: "java/lang/Exception".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Athrow),
PhoronLabel("Label2".to_string()),
PhoronLabel("Handler".to_string()),
JvmInstruction(Pop),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Exception Caught".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/Catcher.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_anewarray() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/Anewarray.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "Anewarray".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(4)),
JvmInstruction(Bipush(10)),
JvmInstruction(Anewarray {
component_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/Thread".to_string(),
},
}),
JvmInstruction(Astore1),
JvmInstruction(Iconst2),
JvmInstruction(Anewarray {
component_type: PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Astore2),
JvmInstruction(Aload2),
JvmInstruction(Iconst0),
JvmInstruction(Bipush(5)),
JvmInstruction(Anewarray {
component_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/String".to_string(),
},
}),
JvmInstruction(Aastore),
JvmInstruction(Aload2),
JvmInstruction(Iconst1),
JvmInstruction(Bipush(5)),
JvmInstruction(Anewarray {
component_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/String".to_string(),
},
}),
JvmInstruction(Aastore),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/Anewarray.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_args_to_main() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/ArgsToMain.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "ArgsToMain".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload0),
JvmInstruction(Arraylength),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/ArgsToMain.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_count_jasmin2() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/CountJasmin2.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "CountJasmin2".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(4)),
JvmInstruction(Iconst0),
JvmInstruction(Istore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Astore2),
PhoronLabel("loop".to_string()),
JvmInstruction(Aload2),
JvmInstruction(Iload1),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Iinc {
varnum: 1,
delta: 1,
}),
JvmInstruction(Iload { varnum: 1 }),
JvmInstruction(Bipush(10)),
JvmInstruction(Ificmplt {
label: "loop".to_string(),
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/CountJasmin2.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_add_nums_jasmin() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/AddNumsJasmin.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "AddNumsJasmin".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "addNums".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer), BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Iload0),
JvmInstruction(Iload1),
JvmInstruction(Iadd),
JvmInstruction(Ireturn),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Iconst1),
JvmInstruction(Bipush(99)),
JvmInstruction(Invokestatic {
class_name: "AddNumsJasmin".to_string(),
method_name: "addNums".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer), BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/AddNumsJasmin.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_stack_push_jasmin() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/StackPushJasmin.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "StackPushJasmin".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(40)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Iconstm1),
JvmInstruction(Iconst0),
JvmInstruction(Iconst1),
JvmInstruction(Iconst2),
JvmInstruction(Iconst3),
JvmInstruction(Iconst4),
JvmInstruction(Iconst5),
JvmInstruction(Lconst0),
JvmInstruction(Lconst1),
JvmInstruction(Fconst0),
JvmInstruction(Fconst1),
JvmInstruction(Dconst0),
JvmInstruction(Dconst1),
JvmInstruction(Bipush(10)),
JvmInstruction(Sipush(1000)),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello, world".to_string()))),
JvmInstruction(Ldcw(LdcwValue::QuotedString("Hola, mundo".to_string()))),
JvmInstruction(Ldc2w(Ldc2wValue::Long(12345))),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/StackPushJasmin.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_factorial_goto() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/FactorialGoto.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "FactorialGoto".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "factorial".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Iconst1),
JvmInstruction(Istore1),
JvmInstruction(Iconst2),
JvmInstruction(Istore2),
PhoronLabel("floop".to_string()),
JvmInstruction(Iload2),
JvmInstruction(Iload0),
JvmInstruction(Ificmpgt {
label: "back".to_string(),
}),
JvmInstruction(Iload1),
JvmInstruction(Iload2),
JvmInstruction(Imul),
JvmInstruction(Istore1),
JvmInstruction(Iinc {
varnum: 2,
delta: 1,
}),
JvmInstruction(Goto {
label: "floop".to_string(),
}),
PhoronLabel("back".to_string()),
JvmInstruction(Iload1),
JvmInstruction(Ireturn),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Bipush(10)),
JvmInstruction(Invokestatic {
class_name: "FactorialGoto".to_string(),
method_name: "factorial".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/FactorialGoto.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_factorial_jasmin() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/FactorialJasmin.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "FactorialJasmin".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "factorial".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Iconst1),
JvmInstruction(Istore1),
JvmInstruction(Iconst2),
JvmInstruction(Istore2),
PhoronLabel("loop".to_string()),
JvmInstruction(Iload2),
JvmInstruction(Iload1),
JvmInstruction(Imul),
JvmInstruction(Istore1),
JvmInstruction(Iinc {
varnum: 2,
delta: 1,
}),
JvmInstruction(Iload2),
JvmInstruction(Iload0),
JvmInstruction(Ificmple {
label: "loop".to_string(),
}),
JvmInstruction(Iload1),
JvmInstruction(Ireturn),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Bipush(10)),
JvmInstruction(Invokestatic {
class_name: "FactorialJasmin".to_string(),
method_name: "factorial".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/FactorialJasmin.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_check_array_type() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/CheckArrayType.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "CheckArrayType".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Bipush(5)),
JvmInstruction(Newarray {
component_type: Integer,
}),
JvmInstruction(Astore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Instanceof {
check_type: PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::BaseType(Integer)),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Bipush(10)),
JvmInstruction(Newarray {
component_type: Character,
}),
JvmInstruction(Astore2),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload2),
JvmInstruction(Instanceof {
check_type: PhoronFieldDescriptor::ArrayType {
component_type: Box::new(PhoronFieldDescriptor::BaseType(Integer)),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/CheckArrayType.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_print_hello_10_times() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/PrintHello10Times.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "PrintHello10Times".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Iconst1),
JvmInstruction(Istore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Astore2),
PhoronLabel("loop".to_string()),
JvmInstruction(Aload2),
JvmInstruction(Iload1),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "print".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Aload2),
JvmInstruction(Ldc(LdcValue::QuotedString(" - ".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "print".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Aload2),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Iinc {
varnum: 1,
delta: 1,
}),
JvmInstruction(Iload1),
JvmInstruction(Bipush(10)),
JvmInstruction(Ificmple {
label: "loop".to_string(),
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/PrintHello10Times.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_add_nums() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/AddNums.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "AddNums".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(5)),
PhoronDirective(LimitLocals(8)),
JvmInstruction(New {
class_name: "java/util/Scanner".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "in".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/InputStream".to_string(),
},
}),
JvmInstruction(Invokespecial {
class_name: "java/util/Scanner".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/io/InputStream".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Astore1),
JvmInstruction(Jsr {
label: "ReadNum".to_string(),
}),
JvmInstruction(Istore3),
JvmInstruction(Jsr {
label: "ReadNum".to_string(),
}),
JvmInstruction(Istore { varnum: 4 }),
JvmInstruction(Iload3),
JvmInstruction(Iload { varnum: 4 }),
JvmInstruction(Jsr {
label: "AddNum".to_string(),
}),
JvmInstruction(Istore { varnum: 5 }),
JvmInstruction(Iload { varnum: 5 }),
JvmInstruction(Jsr {
label: "PrintSum".to_string(),
}),
JvmInstruction(Return),
PhoronLabel("PrintSum".to_string()),
JvmInstruction(Astore { varnum: 7 }),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Swap),
JvmInstruction(Invokestatic {
class_name: "java/lang/String".to_string(),
method_name: "valueOf".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Ret { varnum: 7 }),
PhoronLabel("AddNum".to_string()),
JvmInstruction(Astore { varnum: 6 }),
JvmInstruction(Iadd),
JvmInstruction(Ret { varnum: 6 }),
PhoronLabel("ReadNum".to_string()),
JvmInstruction(Astore2),
JvmInstruction(Aload1),
JvmInstruction(Invokevirtual {
class_name: "java/util/Scanner".to_string(),
method_name: "nextInt".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Ret { varnum: 2 }),
],
},
],
},
};
let actual_ast = parse("samples/AddNums.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_count_jasmin() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/CountJasmin.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "CountJasmin".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(4)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Astore1),
JvmInstruction(Bipush(10)),
JvmInstruction(Istore2),
PhoronLabel("loop".to_string()),
JvmInstruction(Bipush(10)),
JvmInstruction(Iload2),
JvmInstruction(Isub),
JvmInstruction(Invokestatic {
class_name: "java/lang/String".to_string(),
method_name: "valueOf".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Astore3),
JvmInstruction(Aload1),
JvmInstruction(Aload3),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Iinc {
varnum: 2,
delta: -1,
}),
JvmInstruction(Iload2),
JvmInstruction(Ifne {
label: "loop".to_string(),
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/CountJasmin.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_string_buffer_demo() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/StringBufferDemo.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "StringBufferDemo".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "sbDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/Object".to_string(),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Aload0),
JvmInstruction(Checkcast {
cast_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/StringBuffer".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello, mundo!".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/lang/StringBuffer".to_string(),
method_name: "append".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/StringBuffer".to_string(),
}),
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(New {
class_name: "java/lang/StringBuffer".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Invokespecial {
class_name: "java/lang/StringBuffer".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Astore1),
JvmInstruction(Aload1),
JvmInstruction(Invokestatic {
class_name: "StringBufferDemo".to_string(),
method_name: "sbDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/Object".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Invokevirtual {
class_name: "java/lang/StringBuffer".to_string(),
method_name: "toString".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/StringBufferDemo.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_array_demo() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "samples/ArrayDemo.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "ArrayDemo".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Object".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Object".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "setArr".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![
ArrayType {
component_type: Box::new(BaseType(Integer)),
},
BaseType(Integer),
BaseType(Integer),
],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(4)),
PhoronDirective(LimitLocals(4)),
JvmInstruction(Aload0),
JvmInstruction(Iload1),
JvmInstruction(Iload2),
JvmInstruction(Iastore),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "printArr".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![
ArrayType {
component_type: Box::new(BaseType(Integer)),
},
BaseType(Integer),
],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(4)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload0),
JvmInstruction(Iload1),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Bipush(5)),
JvmInstruction(Newarray {
component_type: Integer,
}),
JvmInstruction(Astore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(4)),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(0)),
JvmInstruction(Bipush(1)),
JvmInstruction(Invokestatic {
class_name: "ArrayDemo".to_string(),
method_name: "setArr".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![
ArrayType {
component_type: Box::new(BaseType(Integer)),
},
BaseType(Integer),
BaseType(Integer),
],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(1)),
JvmInstruction(Bipush(2)),
JvmInstruction(Iastore),
JvmInstruction(Aload1),
JvmInstruction(Bipush(2)),
JvmInstruction(Bipush(3)),
JvmInstruction(Iastore),
JvmInstruction(Aload1),
JvmInstruction(Bipush(3)),
JvmInstruction(Bipush(4)),
JvmInstruction(Iastore),
JvmInstruction(Aload1),
JvmInstruction(Bipush(4)),
JvmInstruction(Bipush(5)),
JvmInstruction(Iastore),
JvmInstruction(Aload1),
JvmInstruction(Bipush(0)),
JvmInstruction(Invokestatic {
class_name: "ArrayDemo".to_string(),
method_name: "printArr".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![
ArrayType {
component_type: Box::new(BaseType(Integer)),
},
BaseType(Integer),
],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(1)),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(2)),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(3)),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Aload1),
JvmInstruction(Bipush(4)),
JvmInstruction(Iaload),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
],
},
};
let actual_ast = parse("samples/ArrayDemo.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}
#[test]
fn test_parse_all_in_one() -> Result<(), Box> {
let expected_ast = PhoronProgram {
header: PhoronHeader {
sourcefile_def: PhoronSourceFileDef {
source_file: "AllInOne.pho".to_string(),
},
class_or_interface_def: Class(PhoronClassDef {
name: "AllInOne".to_string(),
access_flags: vec![
PhoronClassOrInterfaceAccessFlag::AccSuper,
PhoronClassOrInterfaceAccessFlag::AccPublic,
],
}),
super_def: PhoronSuperDef {
super_class_name: "java/lang/Thread".to_string(),
},
implements_defs: vec![],
},
body: PhoronBody {
field_defs: vec![
PhoronFieldDef {
name: "x".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPrivate],
field_descriptor: BaseType(Integer),
init_val: None,
},
PhoronFieldDef {
name: "y".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPrivate],
field_descriptor: BaseType(Double),
init_val: Some(PhoronFieldInitValue::Double(1.2345)),
},
PhoronFieldDef {
name: "z".to_string(),
access_flags: vec![PhoronFieldAccessFlag::AccPublic],
field_descriptor: BaseType(Integer),
init_val: Some(PhoronFieldInitValue::Integer(12345)),
},
PhoronFieldDef {
name: "PREFIX".to_string(),
access_flags: vec![
PhoronFieldAccessFlag::AccPublic,
PhoronFieldAccessFlag::AccStatic,
PhoronFieldAccessFlag::AccFinal,
],
field_descriptor: ObjectType {
class_name: "java/lang/String".to_string(),
},
init_val: Some(PhoronFieldInitValue::QuotedString("FooBar".to_string())),
},
],
method_defs: vec![
PhoronMethodDef {
name: "".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPublic],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
JvmInstruction(Aload0),
JvmInstruction(Invokespecial {
class_name: "java/lang/Thread".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "exceptionsDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(1)),
PhoronDirective(Catch {
class_name: "java/lang/Exception".to_string(),
from_label: "Label1".to_string(),
to_label: "Label2".to_string(),
handler_label: "Handler".to_string(),
}),
PhoronLabel("Label1".to_string()),
JvmInstruction(New {
class_name: "java/lang/Exception".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Invokespecial {
class_name: "java/lang/Exception".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Athrow),
PhoronLabel("Label2".to_string()),
PhoronLabel("Handler".to_string()),
JvmInstruction(Pop),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Exception caught".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "finallyDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(3)),
PhoronDirective(LimitLocals(4)),
PhoronDirective(Catch {
class_name: "java/io/FileNotFoundException".to_string(),
from_label: "Start".to_string(),
to_label: "End1".to_string(),
handler_label: "NotFound".to_string(),
}),
PhoronDirective(Catch {
class_name: "java/io/IOException".to_string(),
from_label: "Start".to_string(),
to_label: "End2".to_string(),
handler_label: "IOE".to_string(),
}),
PhoronDirective(Catch {
class_name: "all".to_string(),
from_label: "Start".to_string(),
to_label: "Done".to_string(),
handler_label: "Other_Exception".to_string(),
}),
PhoronLabel("Start".to_string()),
JvmInstruction(New {
class_name: "java/io/FileInputStream".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Ldc(LdcValue::QuotedString("myfile".to_string()))),
JvmInstruction(Invokespecial {
class_name: "java/io/FileInputStream".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Astore1),
PhoronLabel("End1".to_string()),
JvmInstruction(Goto {
label: "Done".to_string(),
}),
PhoronLabel("NotFound".to_string()),
JvmInstruction(Pop),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("No such file".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Goto {
label: "Done".to_string(),
}),
PhoronLabel("IOE".to_string()),
JvmInstruction(Pop),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString(
"IO Exception occurred".to_string(),
))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Goto {
label: "Done".to_string(),
}),
PhoronLabel("End2".to_string()),
PhoronLabel("Done".to_string()),
JvmInstruction(Jsr {
label: "FinalSub".to_string(),
}),
JvmInstruction(Return),
PhoronLabel("Other_Exception".to_string()),
JvmInstruction(Astore2),
JvmInstruction(Jsr {
label: "FinalSub".to_string(),
}),
JvmInstruction(Aload2),
JvmInstruction(Athrow),
PhoronLabel("FinalSub".to_string()),
JvmInstruction(Astore3),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Done".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Ret { varnum: 3 }),
],
},
PhoronMethodDef {
name: "synchronizedMethoDemo".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccSynchronized],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(1)),
PhoronDirective(LimitLocals(1)),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "monitoDemo".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPrivate],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/Object".to_string(),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Aload1),
JvmInstruction(Monitorenter),
JvmInstruction(Aload1),
JvmInstruction(Monitorexit),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "checkCastDemo".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPrivate],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Aload0),
JvmInstruction(Checkcast {
cast_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/Object".to_string(),
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "instanceofDemo".to_string(),
access_flags: vec![PhoronMethodAccessFlag::AccPrivate],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Aload0),
JvmInstruction(Instanceof {
check_type: PhoronFieldDescriptor::ObjectType {
class_name: "java/lang/Thread".to_string(),
},
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Swap),
JvmInstruction(Invokestatic {
class_name: "java/lang/String".to_string(),
method_name: "valueOf".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "subroutinesDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello".to_string()))),
JvmInstruction(Jsr {
label: "PrintString".to_string(),
}),
JvmInstruction(Ldc(LdcValue::QuotedString(", world".to_string()))),
JvmInstruction(Jsr {
label: "PrintString".to_string(),
}),
JvmInstruction(Return),
PhoronLabel("PrintString".to_string()),
JvmInstruction(Astore1),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Swap),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Ret { varnum: 1 }),
],
},
PhoronMethodDef {
name: "lookupswitchDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(2)),
JvmInstruction(Bipush(10)),
JvmInstruction(Istore1),
JvmInstruction(Iload1),
JvmInstruction(Lookupswitch {
switches: vec![
LookupSwitchPair {
key: 1,
label: "R1".to_string(),
},
LookupSwitchPair {
key: 10,
label: "R2".to_string(),
},
LookupSwitchPair {
key: 100,
label: "R3".to_string(),
},
],
default: "R4".to_string(),
}),
PhoronLabel("R1".to_string()),
JvmInstruction(Iconst1),
JvmInstruction(Ireturn),
PhoronLabel("R2".to_string()),
JvmInstruction(Iconst2),
JvmInstruction(Ireturn),
PhoronLabel("R3".to_string()),
JvmInstruction(Iconst3),
JvmInstruction(Ireturn),
PhoronLabel("R4".to_string()),
JvmInstruction(Iconst0),
JvmInstruction(Ireturn),
],
},
PhoronMethodDef {
name: "tableswitchDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(3)),
JvmInstruction(Iconst3),
JvmInstruction(Istore1),
JvmInstruction(Iload1),
JvmInstruction(Tableswitch {
low: 1,
high: 3,
switches: vec!["R1".to_string(), "R2".to_string(), "R3".to_string()],
default: "R4".to_string(),
}),
PhoronLabel("R1".to_string()),
JvmInstruction(Iconst1),
JvmInstruction(Ireturn),
PhoronLabel("R2".to_string()),
JvmInstruction(Iconst2),
JvmInstruction(Ireturn),
PhoronLabel("R3".to_string()),
JvmInstruction(Iconst3),
JvmInstruction(Ireturn),
PhoronLabel("R4".to_string()),
JvmInstruction(Iconst0),
JvmInstruction(Ireturn),
],
},
PhoronMethodDef {
name: "varDemo".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPrivate,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitLocals(1)),
PhoronDirective(Var {
varnum: 0,
name: "Count".to_string(),
field_descriptor: BaseType(Integer),
from_label: "Label1".to_string(),
to_label: "Label2".to_string(),
}),
PhoronLabel("Label1".to_string()),
JvmInstruction(Bipush(10)),
JvmInstruction(Istore0),
PhoronLabel("Label2".to_string()),
JvmInstruction(Return),
],
},
PhoronMethodDef {
name: "main".to_string(),
access_flags: vec![
PhoronMethodAccessFlag::AccPublic,
PhoronMethodAccessFlag::AccStatic,
],
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ArrayType {
component_type: Box::new(ObjectType {
class_name: "java/lang/String".to_string(),
}),
}],
return_descriptor: VoidDescriptor,
},
instructions: vec![
PhoronDirective(LimitStack(2)),
PhoronDirective(LimitLocals(3)),
PhoronDirective(Throws {
class_name: "java/lang/RuntimeException".to_string(),
}),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Ldc(LdcValue::QuotedString("Hello, world".to_string()))),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Invokestatic {
class_name: "AllInOne".to_string(),
method_name: "exceptionsDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Invokestatic {
class_name: "AllInOne".to_string(),
method_name: "finallyDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(New {
class_name: "AllInOne".to_string(),
}),
JvmInstruction(Dup),
JvmInstruction(Invokespecial {
class_name: "AllInOne".to_string(),
method_name: "".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Astore1),
JvmInstruction(Aload1),
JvmInstruction(Invokevirtual {
class_name: "AllInOne".to_string(),
method_name: "instanceofDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Aload1),
JvmInstruction(Invokevirtual {
class_name: "AllInOne".to_string(),
method_name: "checkCastDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Invokestatic {
class_name: "AllInOne".to_string(),
method_name: "subroutinesDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Invokestatic {
class_name: "AllInOne".to_string(),
method_name: "lookupswitchDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Jsr {
label: "PrintInt".to_string(),
}),
JvmInstruction(Invokestatic {
class_name: "AllInOne".to_string(),
method_name: "tableswitchDemo".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![],
return_descriptor: FieldDescriptor(BaseType(Integer)),
},
}),
JvmInstruction(Jsr {
label: "PrintInt".to_string(),
}),
JvmInstruction(Return),
PhoronLabel("PrintInt".to_string()),
JvmInstruction(Astore2),
JvmInstruction(Getstatic {
class_name: "java/lang/System".to_string(),
field_name: "out".to_string(),
field_descriptor: ObjectType {
class_name: "java/io/PrintStream".to_string(),
},
}),
JvmInstruction(Swap),
JvmInstruction(Invokestatic {
class_name: "java/lang/String".to_string(),
method_name: "valueOf".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![BaseType(Integer)],
return_descriptor: FieldDescriptor(ObjectType {
class_name: "java/lang/String".to_string(),
}),
},
}),
JvmInstruction(Invokevirtual {
class_name: "java/io/PrintStream".to_string(),
method_name: "println".to_string(),
method_descriptor: PhoronMethodDescriptor {
param_descriptor: vec![ObjectType {
class_name: "java/lang/String".to_string(),
}],
return_descriptor: VoidDescriptor,
},
}),
JvmInstruction(Ret { varnum: 2 }),
],
},
],
},
};
let actual_ast = parse("samples/AllInOne.pho")?;
assert_eq!(expected_ast, actual_ast);
Ok(())
}