If the atom is in the system, it has to have an id. Likewise, if you want to have an angle or dihedral calculated, it has to have an id. The programming language used to generate the code to number the items in your system is unlikely to be the biggest bottleneck. I’ve done comparable programs in python and in fortran for printing the topology of polymer chains. I didn’t notice a huge difference in ease between using those two languages. The biggest help was having a list of patterns available to use on a system that had atoms consistently numbered based on their position in the repeat unit. Have you thought about what recurring patterns you can use as templates? What I mean by patterns is, for example, if i is a carbon with two carbon bonds, then angles “i-1 i i+1”, “i-1 i i+2” “i-1 i i+3” exist so you can just write out angles j, j+1, j+2 and move on to the next atom. The same thing can be done with dihedrals.
Speaking from experience, making the code extremely general was too much trouble and I abandoned my effort to do so. Unless you have a basically random system with any atom bonded to any other atom type and no discernable relation between their atom ids, I wouldn’t bother. Take advantage of the repeat unit nature of your system as much as possible. If you make a special type of atom at branch points, chain ends, and ring closures, you can then set up functions to treat those atoms as special cases.